#Value working for one class, but not the other - java

I'm struggling with #Value annotation in my API.
My values are stored in the application.properties file in Spring Boot.
secretKey=trullySecretKey
I created one #Component class for a JWT Key:
#Component
public class SecretKeyProperties {
#Value("${secretKey}")
private String secretKey;
public String getSecretKey() {
return this.secretKey;
}
}
And using it ar my JWT class:
#Service
public class JwtUtil {
#Autowired
SecretKeyProperties secretKeyProperties;
private Claims extractAllClaims(String token) {
return Jwts.parser().setSigningKey(secretKeyProperties.getSecretKey()).parseClaimsJws(token).getBody();
}...
Works fine.
But when I do exactly the same, but with a Component for Mail properties setup:
#Mail properties
auth=mail.smtp.auth
authValue=true
starttls=mail.smtp.starttls.enable
starttlsValue = true
host=mail.smtp.host
hostValue=smtp.gmail.com
ssl=mail.smtp.ssl.enable
sslValue=true
sender=test#email.com
password=myPassword
The class:
#Component
public class MailProperties {
#Value("${auth}")
private String auth;
#Value("${starttls}")
private String starttls;
#Value("${host}")
private String host;
#Value("${ssl}")
private String SSL;
#Value("${authValue}")
private boolean authValue;
#Value("${starttlsValue}")
private boolean starttlsValue;
#Value("${hostValue}")
private String hostValue;
#Value("${sslValue}")
private boolean sslValue;
#Value("${sender}")
private String sender;
#Value("${password}")
private String password;
public String getAuth() {
return this.auth;
}
public String getStarttls() {
return this.starttls;
}
public String getHost() {
return this.host;
}
public String getSsl() {
return this.ssl;
}
public boolean getAuthValue() {
return this.authValue;
}
public boolean getStarttlsValue() {
return this.starttlsValue;
}
public String getHostValue() {
return this.hostValue;
}
public boolean getSslValue() {
return this.sslValue;
}
public String getSender() {
return this.sender;
}
public String getPassword() {
return this.password;
}
And the implementation:
#Service
public class MessageBuilder {
#Autowired
MailProperties mailProperties;
public static Properties properties;
public static Session session;
public Properties setupProperties(){
Properties properties = new Properties();
properties.put(mailProperties.getAuth(), mailProperties.getAuthValue());
properties.put(mailProperties.getStarttls(), mailProperties.getStarttlsValue());
properties.put(mailProperties.getHost(), mailProperties.getHostValue());
properties.put(mailProperties.getSsl(), mailProperties.getSslValue());
return properties;
}
I get an error
Cannot invoke "com.plaincoded.restapi.configuration.MailProperties.toString()" because "this.mailProperties" is null
It would make sense if it did not work on both occasions, but only in one?
Why could that be?
Update:

Related

Why no constraint violations found using javax.validation.Validator? When object not populated with values

multi-tenant-database-config-invalid-no-schema.yml:
tenants:
"001":
tenantId: "001"
configuration:
database:
url: "jdbc:postgresql://localhost:5432/postgres?currentSchema=001"
username: "postgres"
J-Unit class:
public class AppTest {
#Test
public void testInvalid() throws Exception {
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory());
File multiTenantConfigurationFile = getMultiTenantTestConfiguration("config/multi-tenant-database-config-invalid-no-schema.yml");
DatabaseEnabledTenants databaseEnabledTenants = objectMapper.readValue(multiTenantConfigurationFile, DatabaseEnabledTenants.class);
Set<ConstraintViolation<DatabaseEnabledTenants>> constraintViolations = validator
.validate(databaseEnabledTenants);
Assertions.assertEquals(0, constraintViolations.size()); // <- Expect this to fail!
}
private File getMultiTenantTestConfiguration(String filename) throws URISyntaxException {
ClassLoader classLoader = getClass().getClassLoader();
URL resource = classLoader.getResource(filename);
File file = new File(resource.toURI());
return file;
}
}
DatabaseEnabledTenants.java:
#Valid
#Component
#ConfigurationProperties(prefix = "multi-tenancy")
public class DatabaseEnabledTenants {
#Valid
#NotNull private Map<String, DatabaseEnabledTenant> tenants = new HashMap<>();
public Map<String, DatabaseEnabledTenant> getTenants() {
return tenants;
}
public void setTenants(Map<String, DatabaseEnabledTenant> tenants) {
this.tenants = tenants;
}
}
DatabaseEnabledTenant.java:
#Valid
public class DatabaseEnabledTenant extends TenantDetails {
#Valid
#NotNull private Configuration configuration;
/** Empty constructor, values populated later. */
public DatabaseEnabledTenant() {}
public Configuration getConfiguration() {
return configuration;
}
public void setConfiguration(Configuration configuration) {
this.configuration = configuration;
}
}
Configuration.java:
public class Configuration {
#NotNull private Database database;
public Configuration() {}
public Database getDatabase() {
return database;
}
public void setDatabase(Database database) {
this.database = database;
}
}
Database.java:
public class Database {
#JsonProperty("url")
#NotBlank(message = "RL must not be blank in tenant configuration")
#SchemaNameInJdbcUrlConstraint
private String jdbcUrl;
#NotBlank(message = "Database username must not be blank in tenant configuration")
private String username;
#NotNull(message = "Database password must not be null in tenant configuration")
private String password;
public Database() {}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

IncompatibleClassChangeError Exception

I'm using OpenPojo for validating getter and setter methods of a class.
But while trying to validate my getter and setter methods I'm having following exception:
java.lang.IncompatibleClassChangeError: class com.openpojo.reflection.java.bytecode.asm.SubClassCreator has
interface org.objectweb.asm.ClassVisitor as super class
Here is my code:
public final class ClientToken implements RememberMeAuthenticationToken {
private static final long serialVersionUID = 3141878022445836151L;
private final String clientName;
private final Credentials credentials;
private String userId;
private boolean isRememberMe;
public ClientToken(final String clientName, final Credentials credentials) {
this.clientName = clientName;
this.credentials = credentials;
}
public void setUserId(final String userId) {
this.userId = userId;
}
public void setRememberMe(boolean isRememberMe) {
this.isRememberMe = isRememberMe;
}
public String getClientName() {
return this.clientName;
}
public Object getCredentials() {
return this.credentials;
}
public Object getPrincipal() {
return this.userId;
}
#Override
public String toString() {
return CommonHelper.toString(ClientToken.class, "clientName", this.clientName, "credentials", this.credentials,
"userId", this.userId);
}
public boolean isRememberMe() {
return isRememberMe;
}
}
Does anybody help me why this problem occurs.

JUnit application.properties always returning null

I am trying to write unit tests for #Service annotated class. I have application.properties file set and a class to access the values.
#Component
#ConfigurationProperties
#PropertySource("classpath:application.properties")
public class ApplicationProperties {
private String first_name;
private String last_name;
private String base_url;
public String getFirst_name() {
return first_name;
}
public void setFirst_name(String firstName) {
this.first_name = firstName;
}
public String getLast_name() {
return last_name;
}
public void setFirst_name(String lastName) {
this.last_name = lastName;
}
public String getBase_url() {
return base_url;
}
public void setBase_url(String baseUrl) {
this.base_url = baseUrl;
}
}
and the test I wrote is like this
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = { ApplicationProperties.class })
#TestPropertySource(locations="classpath:application.properties")
public class ServiceTests {
#Autowired
private ApplicationProperties applicationProperties;
#Before
private void initializeConfig() {
Mockito.when(applicationProperties.getFirst_name()).thenReturn("Karan");
}
#Test
public void sample_Test() {
MyService myService = new MyService();
String fName = myService.getUserFirstName();
assertEquals(fName, "Karan");
}
}
and the method myService.getUserFirstName is like this
#Service
public class MyService {
#Autowired
private ApplicationProperties applicationProperties;
public String getUserFirstName() {
return applicationProperties.getFirst_name();
}
}
I tried following ways provided in this tutorial and this, this and this stackoverflow questions. But it always have applicationProperties object null in the getUserFirstName method and throws null value exception.
Any suggestion what I am doing wrong.

Builder pattern with spring boot #component annotated class

I am a newbie with spring. I am trying to build a URL using the properties from application.properties file in a spring boot project using the org.springframework.beans.factory.annotation.Value annotation.
The class ElasticConfiguration picks the properties from the property file. But, there can be scenarios where the port and protocol are optional.
#Component
public class ElasticConfiguration {
#Value("${elasticsearch.hostname}")
String hostname;
#Value("${elasticsearch.portnumber}")
Integer portnumber;
#Value("${elasticsearch.protocol}")
String protocol;
public String getHostname() {
return hostname;
}
public void setHostname(String hostname) {
this.hostname = hostname;
}
public Integer getPortnumber() {
return portnumber;
}
public void setPortnumber(Integer portnumber) {
this.portnumber = portnumber;
}
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
}
To solve it i am using a builder class which builds the URL object basing on the available properties
public class URL {
private final String _hostname;
private final String _portnumber;
private final String _protocol;
private URL(URLBuilder builder){
this._hostname = builder._hostname;
this._portnumber = builder._portnumber;
this._protocol = builder._protocol;
}
public String get_hostname() {
return _hostname;
}
public String get_portnumber() {
return _portnumber;
}
public String get_protocol() {
return _protocol;
}
public static class URLBuilder {
private final String _hostname;
private String _portnumber;
private String _protocol;
public URLBuilder(String hostname){
this._hostname = hostname;
}
public URLBuilder portNumber(String value) {
this._portnumber = value;
return this;
}
public URLBuilder protocol(String value) {
this._protocol = value;
return this;
}
public URL build() {
return new URL(this);
}
}
#Override
public String toString() {
return "URL [_hostname=" + _hostname + ", _portnumber=" + _portnumber + ", _protocol=" + _protocol + "]";
}
}
I would like to use a builder approach in the spring boot #component annotated class.
Is this the right way to do in spring boot?
Is spring boot providing any such API's already to simulate the builder pattern?
How to integrate above two classes to achieve what i want?
use lombok.jar and it will have #builder which will solve your problem

Spring boot jdbc Connection

i'm trying to configure spring boot in order to have tomcat connection pool to my production database.
My application is NOT web (i have also some difficult to tell that to spring).
I have a Startup class and 3 more classes
the code
#Configuration
#EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class)
public class Starter {
private static Logger logger;
#Autowired
private static MyController controller;
public static void main(String[] args) {
// SpringApplication.setWebEnvironment(false);
SpringApplication.run(Starter.class, args);
LogbackConfigLoader lcl = new LogbackConfigLoader();
if (lcl.init()) {
logger = LoggerFactory.getLogger(Starter.class);
logger.debug("Initialized....");
}
else{
logger = LoggerFactory.getLogger(Starter.class);
}
logger.info(controller.getProva());
}
}
here is the configuration
`
#Configuration
#ConfigurationProperties(prefix="datasource.NIS")
public class NISDBConfiguration {
private String jdbcInterceptors;
private long validationInterval = 30000;
private org.apache.tomcat.jdbc.pool.DataSource pool;
#Value("${driver-class-name}")
private String driverClassName;
#Value("${url}")
private String url;
#Value("${username}")
private String username;
#Value("${password}")
private String password;
#Value("${maxActive}")
private int maxActive = 30;
#Value("${maxIdle}")
private int maxIdle = 8;
#Value("${minIdle}")
private int minIdle = 8;
#Value("${initialSize}")
private int initialSize = 10;
private String validationQuery;
private boolean testOnBorrow;
private boolean testOnReturn;
private boolean testWhileIdle;
private Integer timeBetweenEvictionRunsMillis;
private Integer minEvictableIdleTimeMillis;
private Integer maxWaitMillis;
public String getJdbcInterceptors() {
return jdbcInterceptors;
}
public void setJdbcInterceptors(String jdbcInterceptors) {
this.jdbcInterceptors = jdbcInterceptors;
}
public long getValidationInterval() {
return validationInterval;
}
public void setValidationInterval(long validationInterval) {
this.validationInterval = validationInterval;
}
public org.apache.tomcat.jdbc.pool.DataSource getPool() {
return pool;
}
public void setPool(org.apache.tomcat.jdbc.pool.DataSource pool) {
this.pool = pool;
}
public String getDriverClassName() {
return driverClassName;
}
public void setDriverClassName(String driverClassName) {
this.driverClassName = driverClassName;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getMaxActive() {
return maxActive;
}
public void setMaxActive(int maxActive) {
this.maxActive = maxActive;
}
public int getMaxIdle() {
return maxIdle;
}
public void setMaxIdle(int maxIdle) {
this.maxIdle = maxIdle;
}
public int getMinIdle() {
return minIdle;
}
public void setMinIdle(int minIdle) {
this.minIdle = minIdle;
}
public int getInitialSize() {
return initialSize;
}
public void setInitialSize(int initialSize) {
this.initialSize = initialSize;
}
public String getValidationQuery() {
return validationQuery;
}
public void setValidationQuery(String validationQuery) {
this.validationQuery = validationQuery;
}
public boolean isTestOnBorrow() {
return testOnBorrow;
}
public void setTestOnBorrow(boolean testOnBorrow) {
this.testOnBorrow = testOnBorrow;
}
public boolean isTestOnReturn() {
return testOnReturn;
}
public void setTestOnReturn(boolean testOnReturn) {
this.testOnReturn = testOnReturn;
}
public boolean isTestWhileIdle() {
return testWhileIdle;
}
public void setTestWhileIdle(boolean testWhileIdle) {
this.testWhileIdle = testWhileIdle;
}
public Integer getTimeBetweenEvictionRunsMillis() {
return timeBetweenEvictionRunsMillis;
}
public void setTimeBetweenEvictionRunsMillis(
Integer timeBetweenEvictionRunsMillis) {
this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
}
public Integer getMinEvictableIdleTimeMillis() {
return minEvictableIdleTimeMillis;
}
public void setMinEvictableIdleTimeMillis(Integer minEvictableIdleTimeMillis) {
this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
}
public Integer getMaxWaitMillis() {
return maxWaitMillis;
}
public void setMaxWaitMillis(Integer maxWaitMillis) {
this.maxWaitMillis = maxWaitMillis;
}
#Bean(name = "dsNIS")
public DataSource dataSource() {
this.pool = new org.apache.tomcat.jdbc.pool.DataSource();
this.pool.setDriverClassName(getDriverClassName());
this.pool.setUrl(getUrl());
this.pool.setUsername(getUsername());
this.pool.setPassword(getPassword());
this.pool.setInitialSize(getInitialSize());
this.pool.setMaxActive(getMaxActive());
this.pool.setMaxIdle(getMaxIdle());
this.pool.setMinIdle(getMinIdle());
this.pool.setTestOnBorrow(isTestOnBorrow());
this.pool.setTestOnReturn(isTestOnReturn());
this.pool.setTestWhileIdle(isTestWhileIdle());
if (getTimeBetweenEvictionRunsMillis() != null) {
this.pool
.setTimeBetweenEvictionRunsMillis(getTimeBetweenEvictionRunsMillis());
}
if (getMinEvictableIdleTimeMillis() != null) {
this.pool.setMinEvictableIdleTimeMillis(getMinEvictableIdleTimeMillis());
}
this.pool.setValidationQuery(getValidationQuery());
this.pool.setValidationInterval(this.validationInterval);
if (getMaxWaitMillis() != null) {
this.pool.setMaxWait(getMaxWaitMillis());
}
if (this.jdbcInterceptors != null) {
this.pool.setJdbcInterceptors(this.jdbcInterceptors);
}
return this.pool;
}
#PreDestroy
public void close() {
if (this.pool != null) {
this.pool.close();
}
}
#Bean(name = "jdbcNIS")
public JdbcTemplate jdbcTemplate(DataSource dsNIS) {
return new JdbcTemplate(dsNIS);
}
}
`
the repository
package org.hp.data;
#Repository
public class NisRepository {
protected final Logger log = LoggerFactory.getLogger(getClass());
#Autowired
#Qualifier("jdbcNIS")
protected JdbcTemplate jdbc;
public String getItem(long id) {
return jdbc.queryForObject("SELECT * FROM sb_item WHERE id=?", itemMapper, id);
}
private static final RowMapper<String> itemMapper = new RowMapper<String>() {
#Override
public String mapRow(ResultSet rs, int rowNum) throws SQLException {
String item = rs.getString("title");
return item;
}
};
public JdbcTemplate getJdbc() {
return jdbc;
}
public void setJdbc(JdbcTemplate jdbc) {
this.jdbc = jdbc;
}
}
the controller
#Controller
public class MyController {
#Autowired
private NisRepository items;
public NisRepository getItems() {
return items;
}
public void setItems(NisRepository items) {
this.items = items;
}
public String getProva(){
return items.getItem(10);
}
}
But i always get exception when running the application of NullPointerException because MyController is not autowired and is always null.
I also try to create a new instance with new (but i believe that this is not correct because of the spring mvc pattern).
What is the problem here?
Thanks in advance
You are using Spring Boot but are trying very hard not to use it. You also state you aren't using a web application but then why do you have a #Controller?
To fix your problem remove the configuration of the DataSource and JdbcTemplate Spring Boot will configure those for you. This basically means remove your NISDBConfiguration class. Just add the correct properties to the application.properties file.
spring.datasource.driver-class-name=<your-driver-here>
spring.datasource.url=<your-url>
spring.datasource.username=<your-username>
spring.datasource.password=<your-password>
And of course the other properties you need, check the reference guide for more properties.
Remove the #Qualifier from the JdbcTemplate property in your repository and you also don't need the getter and setter. I would suggest using constructor based injection.
package org.hp.data;
#Repository
public class NisRepository {
protected final Logger log = LoggerFactory.getLogger(getClass());
protected final JdbcTemplate jdbc;
#Autowired
public NisRepository(JdbcTemplate jbc) {
this.jdbc=jdbc;
}
public String getItem(long id) {
return jdbc.queryForObject("SELECT * FROM sb_item WHERE id=?", itemMapper, id);
}
private static final RowMapper<String> itemMapper = new RowMapper<String>() {
#Override
public String mapRow(ResultSet rs, int rowNum) throws SQLException {
String item = rs.getString("title");
return item;
}
};
}
If you don't have a web application replace #Controller with #Service.
Then rewrite your starter class.
#SpringBootApplication
public class Starter {
private static Logger logger;
public static void main(String[] args) {
// SpringApplication.setWebEnvironment(false);
ApplicationContext ctx = SpringApplication.run(Starter.class, args);
LogbackConfigLoader lcl = new LogbackConfigLoader();
if (lcl.init()) {
logger = LoggerFactory.getLogger(Starter.class);
logger.debug("Initialized....");
}
else{
logger = LoggerFactory.getLogger(Starter.class);
}
MyController controller = ctx.getBean(MyController.class);
logger.info(controller.getProva());
}
}
Looks like you are also trying to circument spring boots config loading here? Try to work with the framework not against it.
If you don't have a web application don't include the spring-boot-starter-web in your dependencies and also make sure you don't have any other web related things in there. Spring Boot auto detects the web environment and tries to bootstrap classes for that, if those aren't there it will just run as a plain java application.

Categories

Resources