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
Related
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:
I am trying to use Jackson to parse sample json as demonstrated below. However, I the parsing doesn't work (fails without any exceptions - as I get an empty string for event.getAccountId(); What could I be doing wrong?
Thanks!
ObjectMapper om = new ObjectMapper();
String json = "{\"_procurementEvent\" : [{ \"accountId\" : \"3243234\",\"procurementType\" : \"view\"," +
"\"_procurementSubType\" : \"Standard Connector\",\"_quantity\" : \"4\", \"_pricePerMonth\" : \"100.00\"" +
",\"_annualPrice\" : \"1200.00\"}]}";
ProcurementEvent event = om.readValue(json, ProcurementEvent.class);
event.getAccountId(); // returns null
#JsonIgnoreProperties(ignoreUnknown = true)
private static class ProcurementEvent {
private String _accountId;
private String _procurementType;
private String _quantity;
private String _pricePerMonth;
private String _annualPrice;
#JsonProperty("accountId")
public String getAccountId() {
return _accountId;
}
public void setAccountId(String accountId) {
_accountId = accountId;
}
#JsonProperty("procurementType")
public String getProcurementType() {
return _procurementType;
}
public void setProcurementType(String procurementType) {
_procurementType = procurementType;
}
#JsonProperty("_quantity")
public String getQuantity() {
return _quantity;
}
public void setQuantity(String quantity) {
_quantity = quantity;
}
#JsonProperty("_pricePerMonth")
public String getPricePerMonth() {
return _pricePerMonth;
}
public void setPricePerMonth(String pricePerMonth) {
_pricePerMonth = pricePerMonth;
}
#JsonProperty("_annualPrice")
public String getAnnualPrice() {
return _annualPrice;
}
public void setAnnualPrice(String annualPrice) {
_annualPrice = annualPrice;
}
}
In the question, try the following approach:
class ProcurementEvents {
private List<ProcurementEvent> _procurementEvent; // + annotations like #JsonIgnoreProperties, getters/ setters, etc.
}
// json from your example
ProcurementEvents events = om.readValue(json, ProcurementEvents.class);
events.get(0).getAccountId();
I have an application (Spring 4 MVC+Hibernate 4+MySQL+Maven integration example using annotations) , integrating Spring with Hibernate using annotation based configuration.
Here my controller:
#Controller
public class RestController {
#RequestMapping(value = { "/restCallBack" }, method = RequestMethod.GET)
#ResponseBody
public String performCallBack(#RequestBody RestCallBack restCallBack) {
Preconditions.checkNotNull( restCallBack );
return "computerList";
}
but when I put this on the browser I get a 400:
http://localhost:8080/myApp/restCallBack?devideId=devideId&time=time&duplicate=duplicate&snr=snr&station=station&data=data&avgSignal=avgSignal&lat=lat&lng=lng&rssi=rssi&seqNumber=seqNumber
Here the RestCallBack class
public class RestCallCallBack {
private String devideId;
private String time;
private String duplicate;
private String snr;
private String station;
private String data;
private String avgSignal;
private String lat;
private String lng;
private String rssi;
private String seqNumber;
public String getDevideId() {
return devideId;
}
public void setDevideId(String devideId) {
this.devideId = devideId;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getDuplicate() {
return duplicate;
}
public void setDuplicate(String duplicate) {
this.duplicate = duplicate;
}
public String getSnr() {
return snr;
}
public void setSnr(String snr) {
this.snr = snr;
}
public String getStation() {
return station;
}
public void setStation(String station) {
this.station = station;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public String getAvgSignal() {
return avgSignal;
}
public void setAvgSignal(String avgSignal) {
this.avgSignal = avgSignal;
}
public String getLat() {
return lat;
}
public void setLat(String lat) {
this.lat = lat;
}
public String getLng() {
return lng;
}
public void setLng(String lng) {
this.lng = lng;
}
public String getRssi() {
return rssi;
}
public void setRssi(String rssi) {
this.rssi = rssi;
}
public String getSeqNumber() {
return seqNumber;
}
public void setSeqNumber(String seqNumber) {
this.seqNumber = seqNumber;
}
}
Based on the example request query string, it seems like you are attempting to pass request parameters to the server rather than a request body. If so, take a look at #RequestParam, e.g.
#Controller
public class RestController {
#RequestMapping(value = { "/restCallBack" }, method = RequestMethod.GET)
#ResponseBody
public String performCallBack(#RequestParam("devideId") String devideId,
#RequestParam("time") String time,
#RequestParam("duplicate") String duplicate,
/* more request params... */ {
RestCallCallBack restCallCallBack = new RestCallCallBack();
restCallCallBack.setDevideId(devideId);
restCallCallBack.setTime(time);
restCallCallBack.setDuplicate(duplicate);
// set more params...
// perform validation
return "computerList";
}
}
You can also specify which params are optional by by setting the #RequestParam's required attribute to false.
More information available in the Binding request parameters to method parameters with #RequestParam paragraph in the Spring Reference docs.
I have this json response from a server.
{"session_key":"thekey","expires_in":300,"environment":"exttest","country":"SE","private_feed":{"hostname":"priv.api.test.nordnet.se","port":443,"encrypted":true},"public_feed":{"hostname":"pub.api.test.nordnet.se","port":443,"encrypted":true}}
The top level info is parsed fine into the below class. But how do I populate the list of server info?
The code
Response response = baseResource.path("login").queryParam("service", "NEXTAPI")
.queryParam("auth", authParam).request(responseType).post(null);
System.out.println(response);
SessionInfo ses = response.readEntity(SessionInfo.class);
public class SessionInfo {
public String session_key;
public String environment;
public int expires_in;
public String country;
List<ServerInfo> serverInfo = new ArrayList<ServerInfo>();
}
public class ServerInfo {
public String hostname;
public int port;
public boolean encrypted;
}
This works, but I would hope there is a way to convert it in one step since there might be more nested levels in other responses.
ObjectMapper mapper = new ObjectMapper();
ObjectNode json = response.readEntity(ObjectNode.class);
SessionInfo ses = mapper.treeToValue(json, SessionInfo.class);
ServerInfo s1 = mapper.treeToValue(json.get("private_feed"), ServerInfo.class);
ServerInfo s2 = mapper.treeToValue(json.get("public_feed"), ServerInfo.class);
ses.serverInfo.add(s1);
ses.serverInfo.add(s2);
I tried using Jackson, and was able to build the JSON object in one liner. Probably what you are looking for.
import java.io.IOException;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
public class JackSontest {
public static void main(String[] args){
String jstr = "{\"session_key\":\"thekey\",\"expires_in\":300,\"environment\":\"exttest\",\"country\":\"SE\",\"private_feed\":{\"hostname\":\"priv.api.test.nordnet.se\",\"port\":443,\"encrypted\":true},\"public_feed\":{\"hostname\":\"pub.api.test.nordnet.se\",\"port\":443,\"encrypted\":true}}";
System.out.println("Calling jsonToObject...");
ObjectMapper objectMapper = new ObjectMapper();
try {
SessionInfo info = objectMapper.readValue(jstr, SessionInfo.class);
System.out.println("Session_key:- " + info.getSession_key());
System.out.println("Expires_in:- " + info.getExpires_in());
System.out.println("Environment:- " + info.getEnvironment());
System.out.println("Private Feed:- " + info.getPrivate_feed().getHostname());
System.out.println("Public Feed:- " + info.getPublic_feed().getHostname());
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class SessionInfo {
private String session_key;
private String environment;
private int expires_in;
public String getSession_key() {
return session_key;
}
public void setSession_key(String session_key) {
this.session_key = session_key;
}
public String getEnvironment() {
return environment;
}
public void setEnvironment(String environment) {
this.environment = environment;
}
public int getExpires_in() {
return expires_in;
}
public void setExpires_in(int expires_in) {
this.expires_in = expires_in;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
private String country;
private Feed private_feed;
public Feed getPrivate_feed() {
return private_feed;
}
#JsonProperty("private_feed")
public void setPrivate_feed(Feed private_feed) {
this.private_feed = private_feed;
}
private Feed public_feed;
public Feed getPublic_feed() {
return public_feed;
}
#JsonProperty("public_feed")
public void setPublic_feed(Feed public_feed) {
this.public_feed = private_feed;
}
}
class Feed {
private String hostname;
private int port;
private boolean encrypted;
public String getHostname() {
return hostname;
}
public void setHostname(String hostname) {
this.hostname = hostname;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public boolean isEncrypted() {
return encrypted;
}
public void setEncrypted(boolean encrypted) {
this.encrypted = encrypted;
}
}
Output:
Calling jsonToObject...
Session_key:- thekey
Expires_in:- 300
Environment:- exttest
Private Feed:- priv.api.test.nordnet.se
Public Feed:- priv.api.test.nordnet.se
have you tried Gson:
public class Employee
{
private Integer id;
private String firstName;
private String lastName;
private List<String> roles;
private Department department; //Department reference
//Other setters and getters
}
class DepartmentInstanceCreator implements InstanceCreator<Department> {
public Department createInstance(Type type)
{
return new Department("None");
}
}
//Now <strong>use the above InstanceCreator</strong> as below
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Department.class, new DepartmentInstanceCreator());
Gson gson = gsonBuilder.create();
System.out.println(
gson.fromJson("{'id':1,'firstName':'Lokesh','lastName':'Gupta','roles':['ADMIN','MANAGER'],'department':{'deptName':'Finance'}}",
Employee.class));
Output:
Employee [id=1, firstName=Lokesh, lastName=Gupta, roles=[ADMIN, MANAGER], department=Department [deptName=Finance]]
source
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.