Java Spring initialize, call a method on startup - java

I am new to java spring framework, and I am trying to call a method or initialize a method on startup so when the application start, I will be able to see my data from the database on my jsp page. I have try #EventListener, #PostConstruct but nothing is working for me.
This is my WebConfigura class
#Configuration
#ComponentScan("com.store.spring")
#EnableWebMvc
public class WebConfiguration extends WebMvcConfigurerAdapter {
#Bean
public DataSource dataSource() {
final JndiDataSourceLookup lookup = new JndiDataSourceLookup();
lookup.setResourceRef(true);
DataSource dataSource = lookup.getDataSource("jdbc/product_db");
return dataSource;
}
#Bean
public UrlBasedViewResolver resolver() {
UrlBasedViewResolver viewResolver = new UrlBasedViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
viewResolver.setViewClass(JstlView.class);
return viewResolver;
}
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resource/css/**").addResourceLocations("/css/").setCachePeriod(31556926);
}
#Override
public void configureDefaultServletHandling (DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new HeaderInterceptor());
}
}
This is Web Application Initializer class
#Component
public class WebInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(WebConfiguration.class);
// Add context.setCongiglocation("/WEB-INF/spring/dispatcher-config.xml");
ServletRegistration.Dynamic registration = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
registration.addMapping("/");
registration.setLoadOnStartup(1);
ContextLoaderListener listener = new ContextLoaderListener(context);
servletContext.addListener(listener);
}
}
This is the controller class
#Controller
public class ProductController {
#Autowired
private ProductService productService;
#RequestMapping("/index")
public String index(Model model) {
List<Product> listProduct = productService.getPrducts();
model.addAttribute("listProduct", listProduct);
return "index";
}
// Request mapping using SQL tag
#RequestMapping("/location")
public String addLocation(Model model) {
List<Product> listProduct = productService.getPrducts();
model.addAttribute("listProduct", listProduct);
return "location";
}
#RequestMapping("/entry")
public String entry() {
return "Entry";
}
#RequestMapping("/aboutUs")
public String aboutUS() {return "AboutUs";}
#RequestMapping("/deal")
public String deal() {
return "Deal";
}
#RequestMapping("/listProduct")
public String listOrganizationService(Model model) {
List<Product> listProduct = productService.getPrducts();
model.addAttribute("listProduct", listProduct);
return "ListOrganizations";
}
}
This is the header interceptor class
public class HeaderInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
request.setAttribute("title", "We hope you have a scary and fun filled halloween");
String location = request.getParameter("locationName");
if (location != null) {
request.setAttribute("locationName", location);
}
return true;
}
}
This is the method I want to initialize or call on start up. Or at least
some thing close to this
#RequestMapping("/index")
public String index(Model model) {
List<Product> listProduct = productService.getPrducts();
model.addAttribute("listProduct", listProduct);
return "index";
}
I am using index.jsp to call the listProduct to print my data out. Notice that index.jsp is the first jsp that call when the application start. And I want it to ab able to automatic print those data out
<div class="main-container" style="text-align: center">
<c:forEach var="row" items="${listProduct}">
<div class="detail">
<td>ID: <c:out value="${row.id}"></c:out></td>
<br/>
<td>Name: <c:out value="${row.productName}"></c:out></td>
<br/>
<td>Quantity: <c:out value="${row.quantity}"></c:out></td>
<br/>
<td>Price: <c:out value="${row.price}"></c:out></td>
<br/>
<td><div class="few-line"><c:out value="${row.description}"></c:out></div></td>
</div>
</c:forEach>
I hope someone could help me out.
For Example I had this code inside my WebInitializer class, and when I run it I got an error message
#EventListener(ContextRefreshedEvent.class)
public void contextRefreshedEvent(Model model) {
List<Product> productList = productService.getPrducts();
model.addAttribute("productList", productList)
}
Caused by: java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:256)
... 56 more
org.apache.catalina.core.StandardContext.startInternal One or more
listeners failed to start.
org.apache.catalina.core.StandardContext.startInternal Context []
startup failed due to previous errors
org.springframework.web.context.support.AnnotationConfigWebApplicationContext.doClose
Closing Root WebApplicationContext: startup date [Sun Aug 13 10:43:51
EDT 2017]; root of context hierarchy
These are my plug and dependencies for my jar
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/jstl/jstl -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
</dependencies>

Java Spring initialize, call a method on startup
You can annotate a Spring bean's method with #PostConstruct to have Spring call it after it gets constructed. You can also annotate a method with #Autowired to have Spring call it during the construction of that bean. We typically use one of those to call a method on startup, for example to load data from a database into cache.

Related

Request method 'GET' not supported in AWS server Spring Boot REST API status 500

my Rest API is working fine locally but the moment I put the same JAR and run it from cloud server, I can only call the GET API and none of the POST API from Postmen.
Below are my code.
RestController
#CrossOrigin(origins = "*", maxAge = 3600)
#RestController
#RequestMapping("/api/test")
public class TestController {
#GetMapping("/all")
public String allAccess() {
return "Public Content.";
}
#PostMapping("/testpostA")
public ResponseEntity<?> testPostA() {
return ResponseEntity.ok(new MessageResponse("Test POST successfully!"));
}
#PostMapping("/testpostB")
public String testPostB() {
return "String return POST successfully.";
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.eurogain</groupId>
<artifactId>WebPortal</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>WebPortal</name>
<description>Java Spring Boot project for the Eurogain web portal for both internal and external client.</description>
<properties>
<java.version>15</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-envers</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build></project>
WebSecurityConfigurationAdapter
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(
// securedEnabled = true,
// jsr250Enabled = true,
prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
UserDetailsServiceImpl userDetailsService;
#Autowired
private AuthEntryPointJwt unauthorizedHandler;
#Bean
public AuthTokenFilter authenticationJwtTokenFilter() {
return new AuthTokenFilter();
}
#Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
System.out.println("============================ Inside WebSecurityConfig ===========================Ken");
http.csrf().disable().authorizeRequests().anyRequest().permitAll();
}}
Lastly, the web application:
#SpringBootApplication
public class WebPortalApplication {
public static void main(String[] args) {
SpringApplication.run(WebPortalApplication.class, args);
}}
Running the same JAR file locally, no issue on calling all of the POST and GET API. However, when we move the same JAR over to AWS EC2 cloud instance and run it, we can only call the GET API. The following error was thrown at the Postmen console when calling any of the POST API:
However, no issue when calling the GET API:
Server console output - no error:
UPDATE - Round 1
Tested using wget, error 500 as well. No futher info.
UPDATE - Round 2
Tested using wget POST, and after modifying WebSecurityConfig. Here is the screeshot:
Server console contains warning upon the wget POST:
The updated code for WebSecurityConfig:
#Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable();
}
}
Try config cors like that:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
#Configuration
public class CorsConfig {
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
}
};
}
}
The problem was due to the Nginx reverse proxy handling. In localhost, I was using HTTP, but in the dev server, we are only using HTTPS. Thus, I used HTTPS for all the RESTful API URLs.

used #Transactional but still getting : Could not obtain transaction-synchronized Session for current thread

I'm having this error for days, please look into my codes:
error codes:
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
org.springframework.orm.hibernate5.SpringSessionContext.currentSession(SpringSessionContext.java:136)
org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:496)
com.test.dao.DoctorDAOImpl.getDoctor(DoctorDAOImpl.java:34)
com.test.service.MainServiceImpl.getDoctor(MainServiceImpl.java:39)
com.test.controller.MainController.showMain(MainController.java:23)
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.base/java.lang.reflect.Method.invoke(Method.java:566)
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:871)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:777)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:870)
javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:855)
javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
config.java
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.test")
#PropertySource({"classpath:persistence-mysql.properties"})
public class Config {
#Autowired
private Environment env;
private Logger logger = Logger.getLogger(getClass().getName());
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/view/");
viewResolver.setSuffix(".jsp");
System.out.println("\ntesting "+env.getProperty("jdbc.url")+"\n\n");
return viewResolver;
}
#Bean
public DataSource myDataSource() {
// create connection pool
ComboPooledDataSource myDataSource = new ComboPooledDataSource();
// set the jdbc driver
try {
myDataSource.setDriverClass("com.mysql.jdbc.Driver");
}
catch (PropertyVetoException exc) {
throw new RuntimeException(exc);
}
// for sanity's sake, let's log url and user ... just to make sure we are reading the data
logger.info("jdbc.url=" + env.getProperty("jdbc.url"));
logger.info("jdbc.user=" + env.getProperty("jdbc.user"));
// set database connection props
myDataSource.setJdbcUrl(env.getProperty("jdbc.url"));
myDataSource.setUser(env.getProperty("jdbc.user"));
myDataSource.setPassword(env.getProperty("jdbc.password"));
// set connection pool props
myDataSource.setInitialPoolSize(getIntProperty("connection.pool.initialPoolSize"));
myDataSource.setMinPoolSize(getIntProperty("connection.pool.minPoolSize"));
myDataSource.setMaxPoolSize(getIntProperty("connection.pool.maxPoolSize"));
myDataSource.setMaxIdleTime(getIntProperty("connection.pool.maxIdleTime"));
return myDataSource;
}
private Properties getHibernateProperties() {
// set hibernate properties
Properties props = new Properties();
props.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
props.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
return props;
}
// need a helper method
// read environment property and convert to int
private int getIntProperty(String propName) {
String propVal = env.getProperty(propName);
// now convert to int
int intPropVal = Integer.parseInt(propVal);
return intPropVal;
}
#Bean
public LocalSessionFactoryBean sessionFactory(){
// create session factorys
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
// set the properties
sessionFactory.setDataSource(myDataSource());
sessionFactory.setPackagesToScan(env.getProperty("hibernate.packagesToScan"));
sessionFactory.setHibernateProperties(getHibernateProperties());
return sessionFactory;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
// setup transaction manager based on session factory
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory);
return txManager;
}
}
MainServiceImpl.java
package com.test.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.test.dao.DoctorDAO;
import com.test.dao.PatientDAO;
import com.test.entity.Doctor;
import com.test.entity.Patient;
#Service
public class MainServiceImpl implements MainService {
#Autowired
private PatientDAO patientDao;
#Autowired
private DoctorDAO doctorDao;
#Override
#Transactional
public List<Patient> getPatients() {
System.out.println("inside service: getPatients method");
return patientDao.getPatients();
}
#Override
#Transactional
public Patient getPatient(int theId) {
return patientDao.getPatient(theId);
}
#Override
#Transactional
public Doctor getDoctor(int theId) {
return doctorDao.getDoctor(theId);
}
#Override
#Transactional
public void addPatient(Patient thePatient) {
patientDao.savePatient(thePatient);
}
#Override
#Transactional
public void addDoctor(Doctor theDoctor) {
doctorDao.saveDoctor(theDoctor);
}
#Override
#Transactional
public void deletePatient(int theId) {
patientDao.deletePatient(theId);
}
}
MainController.java
package com.test.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import com.test.entity.Doctor;
import com.test.service.MainService;
#Controller
#RequestMapping("main")
public class MainController {
#Autowired
private MainService service;
#RequestMapping("/")
#Transactional
public String showMain(Model theModel) {
System.out.println("inside show Main method");
Doctor theDoctor = service.getDoctor(1);
// List<Patient> thePatients = service.getPatients();
// System.out.println(thePatients);
theModel.addAttribute("doctor", theDoctor);
return "main";
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.practice</groupId>
<artifactId>test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>test</name>
<properties>
<springframework.version>5.0.2.RELEASE</springframework.version>
<springsecurity.version>5.0.0.RELEASE</springsecurity.version>
<hibernate.version>5.4.1.Final</hibernate.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!-- Spring MVC support -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- Spring orm and tx -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- Spring Security Support -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${springsecurity.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${springsecurity.version}</version>
</dependency>
<!-- Spring Security JSP tag support -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>${springsecurity.version}</version>
</dependency>
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<!-- Add MySQL and C3P0 support -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!-- Servlet, JSP and JSTL support -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- to compensate for java 9+ not including jaxb -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
</dependencies>
<build>
<finalName>test</finalName>
<pluginManagement>
<plugins>
<plugin>
<!-- Add maven coordinates: maven-war-plugin -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
DoctorDAOImpl.java
package com.test.dao;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.test.entity.Doctor;
import com.test.entity.Patient;
#Repository
public class DoctorDAOImpl implements DoctorDAO {
#Autowired
private SessionFactory sessionFactory;
#Override
public List<Patient> getPatients(int theId) {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Query<Patient> theQuery = session.createQuery("from Patient p where p.doctor.id=:doctorId");
theQuery.setParameter("doctorId", theId);
List<Patient> result = theQuery.getResultList();
session.getTransaction().commit();
return result;
}
#Override
public Doctor getDoctor(int theId) {
Session session = sessionFactory.getCurrentSession();
return session.get(Doctor.class, theId);
}
#Override
public void saveDoctor(Doctor theDoctor) {
Session session = sessionFactory.getCurrentSession();
session.save(theDoctor);
}
}
PatientDAOImpl.java
package com.test.dao;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.test.entity.Patient;
#Repository
public class PatientDAOImpl implements PatientDAO {
#Autowired
private SessionFactory sessionFactory;
#Override
public List<Patient> getPatients() {
System.out.println("inside repository: getPatients method");
Session session = sessionFactory.getCurrentSession();
Query<Patient> theQuery = session.createQuery("from Patient",Patient.class);
return theQuery.getResultList();
}
#Override
public void savePatient(Patient thePatient) {
Session session = sessionFactory.getCurrentSession();
session.saveOrUpdate(thePatient);
}
#Override
public Patient getPatient(int theId) {
Session session = sessionFactory.getCurrentSession();
return session.get(Patient.class,theId);
}
#Override
public void deletePatient(int theId) {
Session session = sessionFactory.getCurrentSession();
Query theQuery = session.createQuery("delete from Patient where id=:patientId");
theQuery.setParameter("patientId", theId);
theQuery.executeUpdate();
}
}
I'm sorry that I dumped all my code here, but this is the best I could do.
Please consider using the search before posting a question, as this has been asked multiple times on Stack Overflow. Besides #m-deinum's comment (props go to him!) you would have found the answer e.g. here or here or here: Please add #EnableTransactionManagement annotation.

Spring Security OAuth2 get Access Denied on REST Service

I am trying to secure my Spring REST Services with Spring security and OAuth2. I managed to get the tokens:
tokens
But when I try to get an secured rest service I get access denied:
denied
Can anybody tell me why this is happening?
AuthorizationServerConfig:
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
private static String REALM="EXAMPLE_REALM";
#Autowired
private TokenStore tokenStore;
#Autowired
private UserApprovalHandler handler;
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authManager;
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("myRestClient") // client id
.authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.scopes("read", "write", "trust")
.secret("{noop}P#ssw0rd")
.accessTokenValiditySeconds(240).//invalid after 4 minutes.
refreshTokenValiditySeconds(600);//refresh after 10 minutes.
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore).userApprovalHandler(handler)
.authenticationManager(authManager);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.realm(REALM+"/client");
}
}
ResourceServerConfig:
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
private static final String RESOURCE_ID = "SPRING_REST_API";
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID).stateless(false);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http.
anonymous().disable()
.requestMatchers().antMatchers("/api/**")
.and().authorizeRequests()
.antMatchers("/api/**").access("hasRole('ADMIN')")
.and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
}
}
SecurityConfig:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private ClientDetailsService clientService;
#Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
#Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception{
auth
.inMemoryAuthentication()
.withUser("user")
.password(passwordEncoder().encode("password"))
.roles("USER")
.and()
.withUser("admin")
.password(passwordEncoder().encode("admin"))
.roles("ADMIN");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.anonymous().disable()
.authorizeRequests()
.antMatchers("/oauth/token").permitAll()
.antMatchers("/about").authenticated();
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
#Bean
#Autowired
public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore){
TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
handler.setTokenStore(tokenStore);
handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientService));
handler.setClientDetailsService(clientService);
return handler;
}
#Bean
#Autowired
public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception {
TokenApprovalStore store = new TokenApprovalStore();
store.setTokenStore(tokenStore);
return store;
}
}
AboutController (rest service):
#RestController
public class AboutController {
#RequestMapping(value = "/about", method = RequestMethod.GET)
public ResponseEntity<?> home() {
return new ResponseEntity<>("This is a demo application to show how to secure REST API using Spring Security and OAuth2", HttpStatus.OK);
}
}
application.properties:
server.servlet.context-path=/api
security.oauth2.resource.filter-order = 3
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>gs-rest-service</artifactId>
<version>0.1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Thanks in advance!
Got this working. My problem was that in the application.config file I added /api so that for all my services an api folder is in place like: http://localhost:8080/api/about .. in my ResourceServerConfig class I added /api/** as requestMatchers and antMatchers.... the sercurity configuration is looking for serverice after this api prefix folder.... so exposing my about rest is done in this way:
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
private static final String RESOURCE_ID = "SPRING_REST_API";
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID).stateless(false);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http.
anonymous().disable()
.requestMatchers().antMatchers("/about/**")
.and().authorizeRequests()
.antMatchers("/about/**").access("hasRole('ADMIN')")
.and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
}
}
By the way.. I can request the about service with a parameter like in my request screenshot but it works also if i provide the authorization token als a Bearer Token authorization header....
Regards!
Peter

Thymeleaf+Spring, isAuthenticated()/hasRole() not working

I have a problem with isAuthenticated() method. It seems it always return false no matter if the user is logged in or not. Also after calling this method nothing is shown to the end of the html code. In this example:
aaa
<div sec:authorize="isAuthenticated()">
This content is only shown to authenticated users.
</div>
bbb
ccc
only aaa is shown.
Logged user: <span sec:authentication="name">Bob</span>
Roles: <span sec:authentication="principal.authorities">[ROLE_USER, ROLE_ADMIN]</span>
^this code works perfectly, so there should not be a problem with sec: (I guess)
My Thymeleaf config class:
public class ThymeleafConfig extends WebMvcConfigurerAdapter implements ApplicationContextAware {
private ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
#Bean
public ViewResolver viewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
resolver.setCharacterEncoding("UTF-8");
return resolver;
}
#Bean
public TemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setEnableSpringELCompiler(true);
engine.setTemplateResolver(templateResolver());
engine.addDialect(new SpringSecurityDialect());
return engine;
}
private ITemplateResolver templateResolver() {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setApplicationContext(applicationContext);
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".html");
resolver.setTemplateMode(TemplateMode.HTML);
return resolver;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler(
"/css/**")
.addResourceLocations(
"classpath:/static/css/");
}
}
And maven dependencies:
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring4</artifactId>
<version>3.0.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>3.0.2.RELEASE</version>
</dependency>
What could be causing this error?
Change your file pom.xml, and add this these dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
Now in your html file add:
<!DOCTYPE html>
<html lang="es" xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
that is all 😉
<div sec:authorize="isAuthenticated()">
Text visible only to authenticated users.
</div>
Ok, i solved this problem. This is from : https://github.com/thymeleaf/thymeleaf-extras-springsecurity
Requirements (3.0.x)
Spring Framework version 3.0.x to 4.3.x
Spring Security version 3.0.x to 4.2.x
I was using Spring 5.0.0 - with Spring 4.3.13 and Spring Security 4.2.3 everything works fine.

Publishing EAR containing Spring Rest Service in WebLogic 12.1.3

I've built a small project to provide rest services using springframework. the problem is to access this project inside an EAR after publishing this EAR into a WebLogic server.
When I publish this project as an standalone war in my weblogic everything ends well, my SpringWebAppInitializer is loaded as expected when the server starts and I can reach the webservice using the address localhost:7001/internal-webservices/project/12. But when I add this WAR to the EAR, the SpringWebAppInitializer is never invoked.
Any ideas?
Some of my configurations:
The pom.xml:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.1.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.1.RELEASE</version>
</dependency>
<dependency>
My ApplicationContextConfig class:
#Configuration
#EnableWebMvc
#ComponentScan("my_package.*")
public class ApplicationContextConfig {
// No need ViewSolver
// Other declarations if needed ...
}
My WebApplicationInitializer:
public class SpringWebAppInitializer implements WebApplicationInitializer{
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
appContext.register(ApplicationContextConfig.class);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("internal-webservices",
new DispatcherServlet(appContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
// UTF8 Charactor Filter.
FilterRegistration.Dynamic fr = servletContext.addFilter("encodingFilter", CharacterEncodingFilter.class);
fr.setInitParameter("encoding", "UTF-8");
fr.setInitParameter("forceEncoding", "true");
fr.addMappingForUrlPatterns(null, true, "/*");
}
}
And, my RestController class:
#RestController
public class ProjectController {
#RequestMapping(value = "/project/{id}", method = RequestMethod.GET,
produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE })
public List<String> getProject(#PathVariable("id") String id) {
List<String> result = new ArrayList<String>();
result.add("id: "+ id);
return result;
}
}
Regards,
Felipe

Categories

Resources