Where to put static fields used in builder pattern? - java

Using a builder pattern I want to have static fields used in all instances. Do I put them in the Url class or in the UrlBuilder class as static fields or do I extract them into a new class to only hold the static fields?
The expected result is the ability to create a Url instance by using the Builder class and a switch case logic in the UrlBuilder constructor.
Here is a code example:
public class Url {
//required parameters
private String homePage;
private String boardSuffix;
public String getHomePage() {
return homePage;
}
public String getBoardSuffix() {
return boardSuffix;
}
private Url(UrlBuilder builder) {
this.homePage = builder.homePage;
this.boardSuffix = builder.boardSuffix;
}
//Builder class
public static class UrlBuilder {
//required parameters
private String homePage;
private String boardSuffix;
public UrlBuilder(String homePage, String boardSuffix) {
this.homePage = homePage;
this.boardSuffix = boardSuffix;
}
public Url build() {
return new Url(this);
}
}
}
I've tried placing the static fields in a "Constants" enum, but got lost in the reflection of enums, while trying to prepare tests.

Related

Composition or Inheritance for classes with almost similar implementations but different input and outputs for methods?

I have the following classes, which have quite similar method implementations. Only the classes' method inputs and outputs seem to be of different types. When I put it like this, it sounds like a case for inheritance, however, the fact that the inputs and outputs are different and are related to two lambdas, make me wonder if they should remain without any relationship, as one lambda cannot be thought of in place of another (To be a case for inheritance).
My first class looks like the following.
public class JobPersistenceManager {
private String jobIndexName;
private JobLambda JobLambda;
private MyDataPersistence myDataPersistence;
private DataProcessorUtils dataProcessorUtils;
private static final String JOB_ID = "jobId";
private static final String JOB_NAME = "jobName";
#Inject
public JobPersistenceManager(#Named("jobIndexName") String jobIndexName,
JobLambda JobLambda,
MyDataPersistence myDataPersistence) {
this.jobIndexName = jobIndexName;
this.JobLambda = JobLambda;
this.myDataPersistence = myDataPersistence;
createIndexIfNotExists(this.jobIndexName);
}
public SearchDocumentResult searchJob(MyJobInput myJobInput) throws IOException {
return myDataPersistence
.searchDocument(this.jobIndexName,
dataProcessorUtils.transformObjectDataPayloadToMap(myJobInput));
}
public MyJobOutput invokeCreateJobLambdaAndIndexData(final MyJobInput myJobInput)
throws IOException {
String personRequestPayload = dataProcessorUtils.transformObjectDataInputJson(myJobInput);
Map<String, String> createdJobOutput = this.JobLambda.invokeLambda(personRequestPayload);
this.indexCreatedJob(myJobInput, createdPersonOutput);
return MyJobOutput.builder().withJobID(createdJobOutput.get(JOB_ID))
.withJobName(createdJobOutput.get(JOB_NAME)).build();
}
public int indexCreatedJob(final MyJobInput myJobInput,
final Map<String, String> createdJobOutput) throws IOException {
myJobInput = modifyJobInput(myJobInput);
String documentToIndex = dataProcessorUtils.transformObjectDataInputJson(myJobInput);
return myDataPersistence.indexDocument(this.jobIndexName, documentToIndex);
}
private void createIndexIfNotExists(final String indexName) {
if (!myDataPersistence.doesIndexExist(indexName)) {
myDataPersistence.createIndex(CreateIndexInput.builder().indexName(indexName).build());
}
}
}
My second class looks like the following.
public class EmployeePersistenceManager {
private EmployeeLambda employeeLambda;
private MyTestDataPersistence myTestDataPersistence;
private DataProcessorUtils dataProcessorUtils;
private String employeeIndexName;
private static final String PERSON_ID_KEY = "personId";
private static final String PERSON_NAME_KEY = "personName";
#Inject
public EmployeePersistenceManager(#Named("employeeIndexName") String employeeIndexName,
EmployeeLambda employeeLambda,
MyTestDataPersistence myTestDataPersistence,
DataProcessorUtils dataProcessorUtils) {
this.employeeIndexName = employeeIndexName;
this.employeeLambda = employeeLambda;
this.myTestDataPersistence = myTestDataPersistence;
this.dataProcessorUtils = dataProcessorUtils;
createIndexIfNotExists(employeeIndexName);
}
public SearchDocumentResult searchPerson(EmployeeInput employeeInput) throws IOException {
return myTestDataPersistence
.searchDocument(employeeIndexName,
dataProcessorUtils.transformObjectDataPayloadToMap(employeeInput));
}
public EmployeeOutput invokeCreatePersonLambdaAndIndexData(final EmployeeInput employeeInput)
throws IOException {
String personRequestPayload = dataProcessorUtils.transformObjectDataInputJson(employeeInput);
Map<String, String> createdPersonOutput = this.employeeLambda.invokeLambda(personRequestPayload);
this.indexCreatedEmployee(employeeInput, createdPersonOutput);
return EmployeeOutput.builder().withPersonId(createdPersonOutput.get(PERSON_ID_KEY))
.withPersonName(createdPersonOutput.get(PERSON_NAME_KEY)).build();
}
public int indexCreatedEmployee(final EmployeeInput employeeInput,
final Map<String, String> createdPersonOutput) throws IOException {
employeeInput = modifyEmployeeInput(employeeInput);
String documentToIndex = dataProcessorUtils.transformObjectDataInputJson(employeeInput);
return myTestDataPersistence.indexDocument(this.employeeIndexName, documentToIndex);
}
public Map.Entry<String, Map<String, String>> invokeLambda(final String payload) {
return new AbstractMap.SimpleEntry<>(payload, this.employeeLambda.invokeLambda(payload));
}
private void createIndexIfNotExists(final String indexName) {
if (!myTestDataPersistence.doesIndexExist(indexName)) {
myTestDataPersistence.createIndex(CreateIndexInput.builder().indexName(indexName).build());
}
}
}
As you can see, the methods perform almost the same actions. Only the indexCreatedEmployee and indexCreatedJob methods from the classes have an extra step of processing the input.
Should I keep these classes as they are now without any relationships between them, or should I create an abstract persistence manager class and perform the following.
Move createIndexIfNotExists to the abstract class
Create abstract methods search(), invokeLambda() and indexCreatedData() methods and implement them in each child class. The data types MyJobInput and MyEmployeeInput are POJO classes that don't have any relationship. So I guess these methods I mentioned would then take "Object" parameters?
EmployeeLambda and JobLambda are again classes with no relationship between them. Another concern I had towards creating some sort of inheritance was that, Employee Lambda and JobLambda cannot be used inter-changeably. So was wondering if they should inherit the same parent class just because they're both lambda classes.
OR is there another way to go about this? Any advice would be much appreciated. Thank you very much in advance.
As promised yesterday, here is what I would do.
Create a Lambda interface and make JobLambda and EmployeeLambda implement it
public interface Lambda {
Map<String, String> invokeLambda(String payload);
}
public class JobLambda implements Lambda {
//... your implementation
}
public class EmployeeLambda implements Lambda {
//... your implementation
}
Do the same for DataPersistence
public interface DataPersistence {
boolean doesIndexExist(String indexName);
void createIndex(CreateIndexInput createIndexInput);
int indexDocument(String indexName, String documentToIndex);
SearchDocumentResult searchDocument(String indexName, Map<String, String> payloadMap);
}
public class MyDataPersistence implements DataPersistence {
//... your implementation
}
public class MyTestDataPersistence implements DataPersistence {
//... your implementation
}
Then create a parent class PersistenceManager which contains all the duplicated methods, parametrized for the type of input/output:
(Note: I didn't complete everything, but I did something just to make you understand the concept)
public class PersistenceManager<I, O> {
protected static final String ID = "Id";
protected static final String NAME = "Name";
private String indexName;
private Lambda lambda;
private DataPersistence dataPersistence;
private DataProcessorUtils dataProcessorUtils;
public PersistenceManager(String indexName, Lambda lambda, DataPersistence dataPersistence, DataProcessorUtils dataProcessorUtils) {
this.indexName = indexName;
this.lambda = lambda;
this.dataPersistence = dataPersistence;
this.dataProcessorUtils = dataProcessorUtils;
createIndexIfNotExists(indexName);
}
public SearchDocumentResult search(I input) {
return dataPersistence.searchDocument(indexName, dataProcessorUtils.transformObjectDataPayloadToMap(input));
}
public O invokeCreateLambdaAndIndexData(final I input) {
String requestPayload = dataProcessorUtils.transformObjectDataInputJson(input);
Map<String, String> createdOutput = this.lambda.invokeLambda(requestPayload);
//continue generalizing following the same logic
}
public int indexCreated(I input, Map<String, String> createdOutput) {
//continue generalizing following the same logic
}
private void createIndexIfNotExists(final String indexName) {
if (!dataPersistence.doesIndexExist(indexName)) {
dataPersistence.createIndex(CreateIndexInput.builder().indexName(indexName).build());
}
}
}
At this point, you can specialize your classes by simply choosing the parameters
... all the rest of the code will be shared in the parent class.
public class JobPersistenceManager extends PersistenceManager<MyJobInput, MyJobOutput> {
private static final String JOB_ID = "Job" + ID;
private static final String JOB_NAME = "Job" + NAME;
public JobPersistenceManager(String indexName, Lambda lambda, DataPersistence dataPersistence, DataProcessorUtils dataProcessorUtils) {
super(indexName, lambda, dataPersistence, dataProcessorUtils);
}
}
public class EmployeePersistenceManager extends PersistenceManager<MyEmployeeInput, MyEmployeeOutput> {
private static final String EMPLOYEE_ID = "Employee" + ID;
private static final String EMPLOYEE_NAME = "Employee" + NAME;
public EmployeePersistenceManager(String indexName, Lambda lambda, DataPersistence dataPersistence, DataProcessorUtils dataProcessorUtils) {
super(indexName, lambda, dataPersistence, dataProcessorUtils);
}
}
... and use them like this:
PersistenceManager employeePersistenceManager = new EmployeePersistenceManager(...);
employeePersistenceManager.search(employeeInput); //<-- the code is in the base class

Inject value into a static field

Here is my class:
public class DeduplicationErrorMetric extends AbstractErrorMetric {
public static final String DEDUPLICATIONS_METRIC = "deduplications";
public static final String KAFKA_MESSAGES_METRIC = "kafka.messages";
private static String DEDUPLICATION_TOPIC_NAME;
private static final List<Tag> DEDUPLICATION_ERROR_TAGS = List.of(Tag.of("type", "failed"));
private static final List<Tag> KAFKA_ERROR_TAGS = List.of(Tag.of("topic", DEDUPLICATION_TOPIC_NAME),
Tag.of("action", "send"), Tag.of("result", "failure"));
public DeduplicationErrorMetric() {
super(Map.of(
DEDUPLICATIONS_METRIC, DEDUPLICATION_ERROR_TAGS,
KAFKA_MESSAGES_METRIC, KAFKA_ERROR_TAGS
));
}
#Override
public void incrementMetric(String key) {
errorCounters.get(key).increment();
}
}
I have #Value("${kafka.topic.deduplication}") in my application.yml, and I need to insert the value into DEDUPLICATION_TOPIC_NAME before the bean will be created. How can I do it?
You can use the setter to do this but I'd advocate against this practice !
This means your field will be null before a first instance comes and invokes this injection point
Your static field is not final so can lead to modification, thus lead to hard to debug bugs
It will not solve your current problem as the null value will be used in this case for KAFKA_ERROR_TAGS
#Value("${kafka.topic.deduplication}")
private void setDeduplicationTopicName(String deduplicationTopicName) {
this.DEDUPLICATION_TOPIC_NAME = deducplicationTopicName;
}
Instead, maybe try to create a #Singleton bean and use #Value on its fields, then you're sure you have only one instance.
For your list, you can then use #PostConstruct to make sure it's instantiated once
What you could do here is to directly use injection from a properties file.
If it is a SpringBoot app, in you application properties set your kafka.topic.deduplication property (you can have different values for different environments).
This way, Spring will get the value while constructing the bean.
Your code could look something like this:
public class DeduplicationErrorMetric extends AbstractErrorMetric {
public static final String DEDUPLICATIONS_METRIC = "deduplications";
public static final String KAFKA_MESSAGES_METRIC = "kafka.messages";
private static final List<Tag> DEDUPLICATION_ERROR_TAGS = List.of(Tag.of("type", "failed"));
private static final List<Tag> KAFKA_ERROR_TAGS = List.of(Tag.of("topic", deduplicationTopicName),
Tag.of("action", "send"), Tag.of("result", "failure"));
#Value("${kafka.topic.deduplication}")
private String deduplicationTopicName;
public DeduplicationErrorMetric() {
super(Map.of(
DEDUPLICATIONS_METRIC, DEDUPLICATION_ERROR_TAGS,
KAFKA_MESSAGES_METRIC, KAFKA_ERROR_TAGS
));
}
#Override
public void incrementMetric(String key) {
errorCounters.get(key).increment();
}
}
Remove the keyword "static" and then you will be able to change it in the instance.
Static means that the field is locked to the class.
public class DeduplicationErrorMetric extends AbstractErrorMetric {
public static final String DEDUPLICATIONS_METRIC = "deduplications";
public static final String KAFKA_MESSAGES_METRIC = "kafka.messages";
private String DEDUPLICATION_TOPIC_NAME;
private static final List<Tag> DEDUPLICATION_ERROR_TAGS = List.of(Tag.of("type", "failed"));
private List<Tag> KAFKA_ERROR_TAGS = List.of(Tag.of("topic", DEDUPLICATION_TOPIC_NAME),
Tag.of("action", "send"), Tag.of("result", "failure"));
public DeduplicationErrorMetric() {
super(Map.of(
DEDUPLICATIONS_METRIC, DEDUPLICATION_ERROR_TAGS,
KAFKA_MESSAGES_METRIC, KAFKA_ERROR_TAGS
));
}
#Override
public void incrementMetric(String key) {
errorCounters.get(key).increment();
}
public void setTopic(String value){
DEDUPLICATION_TOPIC_NAME = value;
}
}
private void example(){
DeduplicationErrorMetric dem = new DeduplicationErrorMetric();
//Set the instance value directly
dem.DEDUPLICATION_TOPIC_NAME = "Test";
//Set via a function, potentially with other variables.
demo.setTopic("Test");
}
I would also recommend making the variable name lowercase now that it is not static, as good coding practice.

JAVA How can i get a method to accept a parent class and all of it's extended classes?

I apologize if this has been answered before but either i don't know the correct verbiage or my google fu is bad.
I have a TestModel class which has the getters and setters for all the tests I use. Then I have a AdditionalTestModel class that extends the TestModel with additional getters and setters for that specific type of tests.
Now I have BuildTest Class that i want to be able to pass TestModel and any extended classes of TestModel.
public static Class<?> buildTest(Class<?> test, Class<?> template)
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
Class<?> testClass = test.getClass();
Method[] testMethods = testClass.getMethods();
for (Method method : testMethods) {
String name = method.getName();
if (name.startsWith("get")) {
String testMethodType = method.getReturnType().getTypeName();
// additional code removed//
}
}
If instead of Class<?> i was using TestModel it would work for any test that i pass of Class type TestModel. But i want to be able to pass the extended class to this method as well without having to write a method for each extended class. Any recommendations?
Adding information on the models in case it matters.
public class TestModel {
private String testDescription;
private String testName;
private String apiPath;
private String method;
private String expectedTest;
private Map<String, String> header = new HashMap<>();
private Object body;
private String expectedResult;
private String testCaseId;
private String testUUID;
private List testTypes;
public String getTestDescription() {
return testDescription;
}
public void setTestDescription(String testDescription) {
this.testDescription = testDescription;
}
public String getTestName() {
return testName;
}
public void setTestName(String testName) {
this.testName = testName;
}
public String getAPIPath() {
return apiPath;
}
public void setAPIPath(String apiPath) {
this.apiPath = apiPath;
}
public String getExpectedTest() {
return expectedTest;
}
public void setExpectedTest(String testName) {
this.expectedTest = testName;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public Map<String, String> getHeader() {
return header;
}
public void setHeader(Map<String, String> header) {
this.header = header;
}
public Object getBody() {
return body;
}
public void setBody(Object body) {
this.body = body;
}
public String getExpectedResult() {
return expectedResult;
}
public void setExpectedResult(String expectedResult) {
this.expectedResult = expectedResult;
}
public String getTestCaseId() {
return testCaseId;
}
public void setTestCaseId(String testCaseId) {
this.testCaseId = testCaseId;
}
public String getTestUUID() {
return testUUID;
}
public void setTestUUID(String testUUID) {
this.testUUID = testUUID;
}
public List getTestTypes() {
return testTypes;
}
public void setTestTypes(List testTypes) {
this.testTypes = testTypes;
}
}
public class AdditionalTestModel extends TestModel {
#Override public Object getBody() {
return super.getBody();
}
}
Edit: per a request adding the call information here:
#Test(dataProvider = "Default", threadPoolSize = THREADS, timeOut = API_TIME_OUT)
#Description("")
public void sampleTest(AdditionalTestModel testFromDataProvider) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
testSetup(testFromDataProvider);
AdditionalTestModel test = BuildTest.buildTest(testFromDataProvider, template);
Response response = RestAPI.call(test, testEnvironment);
if (null != response) {
ValidateAPIResponse.validateTestModel(test, response);
} else {
Assert.fail("Response is null, probably a bad method.");
}
}
Where testFromDataProvider is passed from a TestNg data provider.
Now LppEdd below already pointed out i could only assign the base class using generics so working on trying it his way, just have not gotten a chance to change things up yet.
Edit: Also realize now my question was bad. Thanks LppEdd. I should have asked How can I get a method to accept an instance of a class and an instance of any extended class
You are close, you just need to use the extends modifier.
If the class passed in as the test and template parameter should be the same exact class type, you can do:
public static <T extends TestModel> Class<T> buildTest(Class<T> test, Class<T> template) { ... }
Otherwise you can do
public static Class<? extends extends TestModel> buildTest(Class<? extends TestModel> test, Class<? extends String> extends TestModel) { ... }
Which will allow different types to be returned and passed in to each parameter.
You can read up on Java generics and wilcards starting here: https://docs.oracle.com/javase/tutorial/java/generics/wildcards.html
Your buildTest method must accept a TestModel class.
You might be looking for something like
public static TestModel buildTest(
final TestModel test,
final TestModel template) {
final Class<? extends TestModel> testClass = test.getClass();
final Method[] testMethods = testClass.getMethods();
for (final Method method : testMethods) {
final String name = method.getName();
if (name.startsWith("get")) {
final String testMethodType = method.getReturnType().getTypeName();
// additional code removed
}
}
// Maybe
return yourNewInstance; // yourNewInstance is a TestModel, or any class extending it
}
The template argument seems unused here (clarify).
What's the wanted return type? (clarify)
Usage example
final TestModel value1 = buildTest(new TestModel(), ...);
final TestModel value2 = buildTest(new AdditionalTestModel(), ...);
This looks to be exactly the same problem as must be solved by test frameworks. For example, see junit (https://junit.org/junit5/).
The core problem is how to obtain the collection of test methods of a class.
A direct solution would be to have the test class be required to answer its test methods, say, Collection<Function<Void, Void>> getTests(); This has several problems, one being that sub-classes must explicitly list their test methods, two being that sub-classes must be careful to add in the test methods from their super-class, and third, this really fits more as static behavior, which would try to shift java instance typing to the class layer, which just isn't supported by java.
An indirect solution would be to require that test methods satisfy a particular pattern (for example, must start with "test" and have no parameters), and use reflection to discover the methods. Or, use an annotation (say, #Test, which is what junit does) to mark out test methods, and again use the java reflection API to discover methods with the marker.

How to provide parameters to a class with static methods without changing the static qualifier on them?

I have a class with static methods:
public class CompletelyStatic {
public final static String PARAM = "abc";
public static String doSomethingSpecial() {
return "qqq" + PARAM;
}
}
These methods are used everywere throughout the code. The new requirement is to load PARAM value from external config. This config is provided via Config object, through dependency injection, i.e.
public class CompletelyStatic {
#Inject
private Config configProvider;
public final static String DEFAULT_PARAM = "abc";
public String doSomethingSpecial() {
return "qqq" + configProvider.getSpecialParam(DEFAULT_PARAM);
}
}
Unfortunately, here I had to change static qualifier on doSomethingSpecial, so everywhere I used it, I have to inject a CompletelyStatic instance. I'd rather avoid that. I could probably do something like that:
public class CompletelyStatic {
public final static String DEFAULT_PARAM = "abc";
public static String doSomethingSpecial(Config configProvider) {
return "qqq" + configProvider.getSpecialParam(DEFAULT_PARAM);
}
}
But if doSomethingSpecial invoked some private methods underneath, I would have to propagate configProvider along. Is there a better solution?
Edit. If CompletelyStatic had some internal private methods, I should then propagate configProvider to them:
public class CompletelyStatic {
public final static String DEFAULT_PARAM = "abc";
public static String doSomethingSpecial(Config configProvider) {
return "qqq" + otherMethod(configProvider);
}
private static String otherMmethod(Config configProvider) {
return "more logic " + configProvider.getSpecialParam(DEFAULT_PARAM);
}
}
Edit 2. To clarify, I have no influence on the Config object. I know it would be nice if it had static methods, but it doesn't.
You might have to do something like this:
public class CompletelyStatic {
#Inject
private Config configProvider;
// Keep a static private instance of your Static class
private static CompletelyStatic cs = new CompletelyStatic();
//If needed, make the constructor of your class private
private CompletelyStatic(){
}
public final static String DEFAULT_PARAM = "abc";
public static String doSomethingSpecial() {
return "qqq" + cs.getConfigProvider().getSpecialParam(DEFAULT_PARAM);
}
public Config getConfigProvider(){
return configProvider;
}
}
Your other private methods will be able to use the configProvider object in a similar manner: cs.getConfigProvider()
Update
public class CompletelyStatic {
public final static String DEFAULT_PARAM = "abc";
//Keep a static reference to the ConfigProvider object.
private static Config configProvider;
public static String doSomethingSpecial(Config configProvider) {
CompletelyStatic.configProvider = configProvider;
return "qqq" + otherMethod(configProvider);
}
// Here, you will not need to parameterize your other methods.
private static String otherMmethod() {
return "more logic " + configProvider.getSpecialParam(DEFAULT_PARAM);
}
}
Hope this helps!
Usually, the configuration object must be a static
public class CompletelyStatic
{
public final static String DEFAULT_PARAM = "abc";
public static String doSomethingSpecial()
{
return "qqq" + Config.getSpecialParam(DEFAULT_PARAM);
}
}
or
public class CompletelyStatic
{
private static String SPECIAL_PARAM = Config.getSpecialParam(DEFAULT_PARAM);
public final static String DEFAULT_PARAM = "abc";
public static String doSomethingSpecial()
{
return "qqq" + SPECIAL_PARAM;
}
}
or
config should be a singleton instance in that case Config.getInstance().getSpecialParam(DEFAULT_PARAM);
Hope this helps :)
The better solution can be loading static Config variable during application startup through an init() like method as shown in the below code. The advantage of this approach is that you don't need to change/modify all of your dependent classes if you are moving from Config to something else. Otherwise, you need to change all of your classes from where you are invoking doSomethingSpecial().
public class CompletelyStatic {
private static Config configProvider;
//you need to load the below init method during application start up
public static void init(Config configProvider) {
CompletelyStatic.configProvider= configProvider;
}
public static String doSomethingSpecial() {
return "qqq" + otherMethod();
}
private static String otherMmethod() {
return "more logic " + configProvider.getSpecialParam(DEFAULT_PARAM);
}
}
Also, in this approach, the method signature public String doSomethingSpecial() did not change from the original class (so no effect to all of the dependent classes, but only point is to load init during start up).

Is a good practice to use static variables for holding properties from file in a Spring MVC project

The code below is working perfectly but I am in doubt if I am using the best approach for the requirenment: read, from a couple of places, property from a properties file in a Spring project. Basically, I created a public class with static variables. Now I am using Spring 3 plus JDK6. I might upgrade Spring to 4 soon but I will not be able to chnage JDK version.
mvc-dispatcher-servlet.xml
Properties File
url = http://localhost:8080/MHE2/
lastpage = log/display/last
firstpage = log/display/first
previouspage = log/display/previous
nextpage = log/display/next
One sample of using the property value. There will be a lot of case like these
//calling rest web service
DefaultHttpClient httpClient = new DefaultHttpClient(); //Apache HttpClient
HttpPost postRequest = new HttpPost(Ut_Properties.getUrl() + Ut_Properties.getLastpage());
Public class with static variables
package com.mastercard.mhe.utilities;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
#Component("ut_Properties")
#Scope("singleton")
public class Ut_Properties {
private static String url;
private static String lastpage;
private static String firstpage;
private static String previouspage;
private static String nextpage;
#Autowired
public Ut_Properties(#Value("${url}") String url,
#Value("${lastpage}") String lastpage,
#Value("${url}") String previouspage,
#Value("${lastpage}") String nextpage) {
Ut_Properties.setUrl(url);
Ut_Properties.setLastpage(lastpage);
Ut_Properties.setUrl(previouspage);
Ut_Properties.setLastpage(nextpage);
}
public static String getUrl() {
return url;
}
public static void setUrl(String url) {
Ut_Properties.url = url;
}
public static String getFirstpage() {
return firstpage;
}
public static void setFirstpage(String firstpage) {
Ut_Properties.firstpage = firstpage;
}
public static String getPreviouspage() {
return previouspage;
}
public static void setPreviouspage(String previouspage) {
Ut_Properties.previouspage = previouspage;
}
public static String getNextpage() {
return nextpage;
}
public static void setNextpage(String nextpage) {
Ut_Properties.nextpage = nextpage;
}
public static String getLastpage() {
return lastpage;
}
public static void setLastpage(String lastpage) {
Ut_Properties.lastpage = lastpage;
}
}
You could use something like this:
#Service
public class MyPropertiesServ implements InitializingBean {
#Autowired
protected ApplicationContext context;
private Properties properties;
private static MyPropertiesServ singleInst;
protected MyPropertiesServ () {
properties = new Properties();
singleInst= this;
}
#Override
public void afterPropertiesSet() throws Exception {
properties.load(context.getResource("classpath:file.properties").getInputStream());
}
public static String getStringProperty(String key) {
return singleInst.properties.getProperty(key);
}
}
Another example:
http://forum.spring.io/forum/spring-projects/container/35703-initialising-static-property-of-class-through-injection-on-startup
#Value is a lovely annotation but looking at your code I'm wondering if it is important for you that those variables representing the properties are static ?
If not you could avoid alot of clutter code by not making them static.
#Component
public class Ut_Properties {
#Value("${url}")
private String url;
// ...
public getUrl() { return url; }
#Component/Service/Controller
public class ClassFromWhereYouWantToAccessTheProperties {
#Inject
Ut_Properties utProperties;
// you could ofcourse just inject the properties in the classes where you need them instead of trying to gather them in one class.
#Value("${url}")
private String url;
public void someRandomMethod() {
utProperties.getUrl();
// vs
this.url;

Categories