Spring Boot #Aspect J logging - java

I created test Spring MVC application with REST controller. I want to apply aspects for my some method, but when this method is called nothing happen and I can't find the reason.
It is my Configuration and Application class:
#SpringBootApplication(scanBasePackages = "org.test")
#EnableAspectJAutoProxy
public class TestaopApplication {
public static void main(String[] args) {
SpringApplication.run(TestaopApplication.class, args);
}
}
It is my aspect class:
#Aspect
#Component
public class Logging {
private static final Logger logger = LoggerFactory.getLogger(GreetingController.class);
#Pointcut("execution(* org.test.restspring.model.Greeting.getCreatedDate(..))")
private void getDate(){}
#Before("getDate()")
public void beforeGettingDate(){
logger.info("Date is asked");
}
#After("getDate()")
public void afterGettingDate(){
logger.info("Date is received");
}
}
It is my simple bean:
#Component
public class Greeting {
private long id;
private String content;
private Date created;
public Greeting() { }
public Greeting(long id, String content) {
this.id = id;
this.content = content;
this.created = Calendar.getInstance().getTime();
}
public long getId() {
return id;
}
public String getContent() {
return content;
}
public String getCreatedDate(){
return created.toString();
}
}
It is my Controller:
#RestController
public class GreetingController {
private static final String template = "Hello, %s!";
private static final Logger logger = LoggerFactory.getLogger(GreetingController.class);
private final AtomicLong counter = new AtomicLong();
#RequestMapping("/greeting")
public Greeting greeting(#RequestParam(value="name", defaultValue="World") String name) {
Greeting response = new Greeting(counter.incrementAndGet(),
String.format(template, name));
logger.info(response.getCreatedDate());
return response;
}
}
Please help me with this problem.

Beans created via explicit constructor call (new Greeting(...)) are not managed by Spring. That is why your aspect is not applied.
You can try to use prototype scope. This way Spring creates new instance of greeting bean for every request.
for bean:
#Component
#Scope("prototype")
public class Greeting {
and your controller:
#RestController
public class GreetingController {
private static final String template = "Hello, %s!";
private static final Logger logger = LoggerFactory.getLogger(GreetingController.class);
private final AtomicLong counter = new AtomicLong();
#Autowired
private Greeting greeting;
#RequestMapping("/greeting")
public Greeting greeting(#RequestParam(value="name", defaultValue="World") String name) {
greeting.setId(counter.incrementAndGet());
greeting.setContent(String.format(template, name))
logger.info(response.getCreatedDate());
return response;
}
}

Related

Java Spring how to fill configuration automatically

i try to authwire configuration using spring
All complies fine and the server is running , but the configurator never triggered
//Main class :
#SpringBootApplication
public class MainApplication {
public static void main(String[] args)
{
SpringApplication app = new SpringApplication(MainApplication.class);
app.setDefaultProperties(Collections
.singletonMap("server.port", "8083"));
app.run(args);
}
}
// this class i like the Map<String, CarsInfo> carsInfos map will be filled automatically
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class AppManager {
private final Map<String, CarsInfo> carsInfos;
#Autowired
public AppManager(Map<String, CarsInfo> carsInfos) {
this.carsInfos = carsInfos;
}
}
public class CarsInfo {
private String id;
private String data;
public CarsInfo(String id,String data) {
this.id = id;
this.data = data;
}
}
#Configuration
public class Config1 {
#Bean ("DATA_FILLER")
public String getData() {
return "Car Test";
}
#Bean(IDs.CAR_ID)
public CarsInfo carInfo(#Qualifier("DATA_FILLER") String data) {
return new CarsInfo(IDs.CAR_ID,data);
}
}
#Configuration
public class Config2 {
#Bean("DATA_FILLER")
public String getData() {
return "Tractor Test";
}
#Bean(IDs.TRACTOR_ID)
public CarsInfo tractorInfo(#Qualifier("DATA_FILLER") String data) {
return new CarsInfo(IDs.CAR_ID,data);
}
}
public class IDs {
public static final String CAR_ID = "car_id";
public static final String TRACTOR_ID = "tractor_id";
}

#Value working for one class, but not the other

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:

Show saved messages from the database MySQL

I created a chat on spring boot. Where several people can correspond. So I created a database and there I store all messages from users. So I want, if a new user enters the chat, then he should see only the last 10 messages. The problem is that the program does not take the last 10 messages from the database, it takes them from the server, this is not correct. I want him to take the last 10 messages from the database.
My code
Rest Controller
#SpringComponent
#org.springframework.web.bind.annotation.RestController
public class RestController {
private List<Message> store;
public RestController() {
store = new ArrayList<>();
}
#PutMapping("/api/save")
public void saveMessage(#RequestBody String chatMessage) {
store.add(new Gson().fromJson(chatMessage, Message.class));
if (store.size() > 10)
store.remove(0);
}
#GetMapping("/api/last")
public String getLasts() {
return new Gson().toJson(store);
}
}
Message class
#Entity
#Table(name = "chatMessages")
public class Message {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String fromV;
private String messageV;
private Timestamp time;
public Timestamp getTime() {
return time;
}
public void setTime(Timestamp time) {
this.time = time;
}
public Message() { }
public String getFromV() {
return fromV;
}
public void setFromV(String fromV) {
this.fromV = fromV;
}
public String getMessageV() {
return messageV;
}
public void setMessageV(String messageV) {
this.messageV = messageV;
}
public Message(String from, String message) {
this.fromV = from;
this.messageV = message;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFrom() {
return fromV;
}
public void setFrom(String from) {
this.fromV = from;
}
public String getMessage() {
return messageV;
}
public void setMessage(String message) {
this.messageV = message;
}
}
MessageRepository
#Repository
public interface MessageRepository extends JpaRepository<Message, Long> {
}
MessageService
public interface MessageService {
void add(Message message);
List<Message> getAllMessages();
}
MessageServiceImpl
#Service
#Transactional
public class MessageServiceImpl implements MessageService {
private final MessageRepository repository;
#Autowired
public MessageServiceImpl(MessageRepository repository) {
this.repository = repository;
}
#Override
public void add(Message message) {
message.setTime(new Timestamp(new Date().getTime()));
repository.saveAndFlush(message);
}
#Override
public List<Message> getAllMessages() {
return repository.findAll();
}
}
MessageList
public MessageList() {
addClassName("message-list");
}
#Override
public void add(Component... components) {
super.add(components);
components[components.length-1]
.getElement()
.callFunction("scrollIntoView");
}
}
Application Controller
server.port=8080
# This is a workaround for https://github.com/vaadin/spring/issues/381
spring.servlet.multipart.enabled = false
spring.datasource.url=jdbc:mysql://localhost:3306/chat?createDatabaseIfNotExist=true&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
To be frankly,i don't understand the purpose of the object store in your controller. If you want to query the last 10 messages.You can just implement a method in repository and invoke it in your controller.
MessageRepository
#Repository
public interface MessageRepository extends JpaRepository<Message, Long> {
List<Message> findTop10ByOrderByTimeDesc();
}

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