Not rollingback data from transaction - java

Why even if exception is thrown data is not rolledback from database
I set rollbackFor = Exception.class and it still doesn't rollback data when second visit is put into databse.
#EnableTransactionManagement
#Service
public class VisitService {
private final static Logger logger = LoggerFactory.getLogger(VisitService.class);
private final VisitRepository visitRepository;
public VisitService(VisitRepository visitRepository) {
this.visitRepository = visitRepository;
}
public List<Visit> findAllByDate(LocalDateTime date){
return visitRepository.findAllByDate(date);
}
#Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = RuntimeException.class, propagation = Propagation.REQUIRED)
public Visit save(#Valid Visit visit) {
logger.info("Inside visitService");
visit.setPayed(false);
if (visit.getPrice().intValue() > 1000)
visit.setDiscount(new BigDecimal(0.05));
else visit.setDiscount(new BigDecimal(0.00));
visitRepository.save(visit);
if(findAllByDate(visit.getDate()).size()>1)
throw new RuntimeException();
return null;
}
}
tried with configuration to transaction
#Configuration
#ConditionalOnClass({PlatformTransactionManager.class})
#AutoConfigureAfter({JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, Neo4jDataAutoConfiguration.class})
#EnableConfigurationProperties({TransactionProperties.class})
public class TransactionAutoConfiguration {
}
part of stack trace
2018-12-08 23:16:23.653 TRACE 3360 --- [nio-8080-exec-2] o.s.t.i.TransactionInterceptor : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
Hibernate: insert into visits (visit_date, description, discount, payed, pet_id, price, vet_id) values (?, ?, ?, ?, ?, ?, ?)
2018-12-08 23:16:23.663 TRACE 3360 --- [nio-8080-exec-2] o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
2018-12-08 23:16:23.664 TRACE 3360 --- [nio-8080-exec-2] o.s.t.i.TransactionInterceptor : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAllByDate]
Hibernate: select visit0_.id as id1_6_, visit0_.visit_date as visit_da2_6_, visit0_.description as descript3_6_, visit0_.discount as discount4_6_, visit0_.payed as payed5_6_, visit0_.pet_id as pet_id6_6_, visit0_.price as price7_6_, visit0_.vet_id as vet_id8_6_ from visits visit0_ where visit0_.visit_date=?
2018-12-08 23:16:23.685 TRACE 3360 --- [nio-8080-exec-2] o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAllByDate]
2018-12-08 23:16:23.685 TRACE 3360 --- [nio-8080-exec-2] o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.samples.petclinic.services.VisitService.save] after exception: java.lang.RuntimeException
2018-12-08 23:16:23.685 TRACE 3360 --- [nio-8080-exec-2] o.s.t.i.RuleBasedTransactionAttribute : Applying rules to determine whether transaction should rollback on java.lang.RuntimeException
2018-12-08 23:16:23.685 TRACE 3360 --- [nio-8080-exec-2] o.s.t.i.RuleBasedTransactionAttribute : Winning rollback rule is: RollbackRuleAttribute with pattern [java.lang.RuntimeException]
2018-12-08 23:16:23.690 DEBUG 3360 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Failed to complete request: java.lang.RuntimeException
2018-12-08 23:16:23.698 ERROR 3360 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.RuntimeException] with root cause
java.lang.RuntimeException: null
There is visitRepository with default annnotations
VisitRepository :
public interface VisitRepository extends Repository<Visit, Integer> {
Visit save(Visit visit) throws DataAccessException;
List<Visit> findByPetId(Integer petId);
Visit findById(Integer visitId);
#Transactional(readOnly = true)
List<Visit> findAllByDate(LocalDateTime date);
Visit findByDate(LocalDateTime date);
}

Related

SQL Warning Code: -1100 SQLState 02000 no data error with Spring Boot JPA Data is not updated into DB

While saving data into MySQL database i am getting below SQL error.
SQL Warning Code: -1100 SQLState 02000 no data error with Spring Boot JPA Data is not updated into DB, Please find Below repository method and Bean Entity. SpringBoot version 2.2.5, Java Version 11, MySQL 5.5 version.
#Modifying(clearAutomatically = true)
#Transactional
public List<Status> resetStatus()
{
logger.info("in resetStatus: reset the value null");
String setBoxval = null;
String setBoxId = null;
List<Status> retRes = new ArrayList<Status>();
Status s = new Status();
try {
entityManager.createQuery("UPDATE UserEntity ue SET ue.boxvalue = :boxVal, boxid = :boxId")
.setParameter("boxVal", setBoxval)
.setParameter("boxId", setBoxId)
.executeUpdate();
s.setResponse("Success");
} catch(Exception ex) {
s.setResponse("failue");
ex.printStackTrace();
}
retRes.add(s);
return retRes;
}
Entity bean:
#Entity
#Table(name="tictacbox")
public class UserEntity
{
#Id
#GeneratedValue
private int id;
#Column(name="boxid")
private Integer boxid;
#Column(name="boxvalue")
private String boxvalue;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Integer getBoxid() {
return boxid;
}
public void setBoxid(Integer boxid) {
this.boxid = boxid;
}
public String getBoxvalue() {
return boxvalue;
}
public void setBoxvalue(String boxvalue) {
this.boxvalue = boxvalue;
}
#Override
public String toString() {
return "userEntity [id=" + id + ", boxId=" + boxid +
", boxvalue=" + boxvalue + "]";
}
}
Log:
2020-04-03 11:25:45.937 INFO 18796 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2020-04-03 11:25:45.943 INFO 18796 --- [ main] com.test.TicTacToe.TicTacToeApplication : Started TicTacToeApplication in 12.471 seconds (JVM running for 13.484)
2020-04-03 11:26:13.855 INFO 18796 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-04-03 11:26:13.856 INFO 18796 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2020-04-03 11:26:13.872 INFO 18796 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 16 ms
2020-04-03 11:26:30.427 INFO 18796 --- [nio-8080-exec-8] com.test.TicTacToe.user.HomeController : resetStatus
2020-04-03 11:26:30.427 INFO 18796 --- [nio-8080-exec-8] com.test.TicTacToe.user.UserService : in service: resetStatus
2020-04-03 11:26:30.457 INFO 18796 --- [nio-8080-exec-8] com.test.TicTacToe.user.UserService : in resetStatus: reset the value null
2020-04-03 11:26:30.839 WARN 18796 --- [nio-8080-exec-8] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Warning Code: -1100, SQLState: 02000
2020-04-03 11:26:30.841 WARN 18796 --- [nio-8080-exec-8] o.h.engine.jdbc.spi.SqlExceptionHelper : no data

Spring - All request are going to the same mapping

I don't know how it happened because I didn't do big changes but now all the request I do to my spring server application are respond by the same service.
My build.gradle (no security at all)
My main (no big deal)
#SpringBootApplication
public class PolifoniaApplication {
public static void main(String[] args) {
SpringApplication.run(PolifoniaApplication.class, args);
}
}
My Controller (every single request goes to '/login' even from another classes, and I even comment the Mapping line and it keeps going to login). Also even non existing URIs it will go to the "/login" service
#CrossOrigin
#RestController
public class UsuarioController {
Logger logger = LoggerFactory.getLogger(UsuarioController.class);
private static final String ESTUDIANTE_GROUP = "ou=people,dc=springframework,dc=org";
private static final String PROFESOR_GROUP = "ou=otherpeople,dc=springframework,dc=org";
private static final String ADMINISTRATIVO_GROUP = "ou=space cadets,dc=springframework,dc=org";
#Autowired
private LdapTemplate ldapTemplate;
#Autowired
private UsuarioRepository usuarioRepository;
#Autowired
private SesionRepository sesionRepository;
#GetMapping("/all")
public List<String> getAllPersonNames() {
return ldapTemplate.search(query().where("objectclass").is("person"), new AttributesMapper<String>() {
public String mapFromAttributes(Attributes attrs) throws NamingException {
return attrs.get("sn").get().toString();
}
});
}
/**
* Servicio de confirmación de login con LDAP o por token
* #param authData - información de seguridad
* #return String con token si se generó
*/
#PostMapping("/login")
#RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> autenticar(#RequestBody AuthData authData) {
ResponseEntity<String> response;
boolean correcto = ldapTemplate.authenticate("", String.format("(uid=%s)", authData.getUsername()), authData.getPassword());
if (correcto) {
Usuario usuario = buscarUsuarioLdap(authData);
Sesion sesion = new Sesion(authData, usuario.getId());
response = ResponseEntity.status(HttpStatus.OK).body(Utilities.stringToJson("token", sesion.getToken()));
sesionRepository.save(sesion);
} else {
throw new AuthPolifoniaException();
}
return response;
}
/**
* Método que registra un usuario que ingresa por primera vez a la aplicación
* #param authData - Datos del usuario
*/
private Usuario buscarUsuarioLdap(AuthData authData) {
Usuario usuario = usuarioRepository.findByUsername(authData.getUsername());
if (usuario == null) {
TipoUsuario tipoUsuario = TipoUsuario.ESTUDIANTE;
LdapQuery estudianteQuery = LdapQueryBuilder.query().base(ESTUDIANTE_GROUP).searchScope(SearchScope.SUBTREE)
.filter(new EqualsFilter("uid", authData.getUsername()));
List<String> result = ldapTemplate.search(estudianteQuery, new AttributesMapper<String>() {
public String mapFromAttributes(Attributes attrs) throws NamingException {
return attrs.get("cn").get().toString();
}
});
if (result.isEmpty()) {
tipoUsuario = TipoUsuario.PROFESOR;
LdapQuery profesorQuery = LdapQueryBuilder.query().base(PROFESOR_GROUP).searchScope(SearchScope.SUBTREE)
.filter(new EqualsFilter("uid", authData.getUsername()));
result = ldapTemplate.search(profesorQuery, new AttributesMapper<String>() {
public String mapFromAttributes(Attributes attrs) throws NamingException {
return attrs.get("cn").get().toString();
}
});
}
if (result.isEmpty()) {
tipoUsuario = TipoUsuario.ADMINISTRATIVO;
LdapQuery administrativoQuery = LdapQueryBuilder.query().base(ADMINISTRATIVO_GROUP)
.searchScope(SearchScope.SUBTREE).filter(new EqualsFilter("uid", authData.getUsername()));
result = ldapTemplate.search(administrativoQuery, new AttributesMapper<String>() {
public String mapFromAttributes(Attributes attrs) throws NamingException {
return attrs.get("cn").get().toString();
}
});
}
if (result.isEmpty()) {
tipoUsuario = null;
}
usuario = new Usuario(result.get(0), authData.getUsername(), tipoUsuario);
usuarioRepository.save(usuario);
}
return usuario;
}
/**
* Servicio que destruye el token de sesión
* #param authData - Datos del usuario (token)
*/
#PostMapping("/logout")
public void logout(#RequestHeader(HttpHeaders.WWW_AUTHENTICATE) String token) {
sesionRepository.deleteById(token);
}
And I have an advice that was working. It seems that if I run my tests it works fine. I cannot find any logic involved, it's madness.
And I tried to comment the method but then there is no answer at all by my server.
This is the log since I send the request (in this case "localhost:8080/comunidades", but it happens with all of the services even "/logout")
2018-11-25 10:50:12.981 DEBUG 11840 --- [nio-8080-exec-3] o.a.tomcat.util.net.SocketWrapperBase : Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper#d601e02:org.apache.tomcat.util.net.NioChannel#75d2ecd0:java.nio.channels.SocketChannel[connected local=/0:0:0:0:0:0:0:1:8080 remote=/0:0:0:0:0:0:0:1:7687]], Read from buffer: [0]
2018-11-25 10:50:12.982 DEBUG 11840 --- [nio-8080-exec-3] org.apache.tomcat.util.net.NioEndpoint : Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper#d601e02:org.apache.tomcat.util.net.NioChannel#75d2ecd0:java.nio.channels.SocketChannel[connected local=/0:0:0:0:0:0:0:1:8080 remote=/0:0:0:0:0:0:0:1:7687]], Read direct from socket: [301]
2018-11-25 10:50:12.983 DEBUG 11840 --- [nio-8080-exec-3] o.a.coyote.http11.Http11InputBuffer : Received [GET /comunidades HTTP/1.1
Content-Type: application/json
cache-control: no-cache
Postman-Token: e30db580-fcdd-4c95-8195-f16b9186420a
User-Agent: PostmanRuntime/7.4.0
Accept: */*
Host: localhost:8080
accept-encoding: gzip, deflate
content-length: 17
Connection: keep-alive
{
"pageNum": 1
}]
2018-11-25 10:50:12.998 DEBUG 11840 --- [nio-8080-exec-3] o.a.c.authenticator.AuthenticatorBase : Security checking request GET /comunidades
2018-11-25 10:50:12.998 DEBUG 11840 --- [nio-8080-exec-3] org.apache.catalina.realm.RealmBase : No applicable constraints defined
2018-11-25 10:50:12.998 DEBUG 11840 --- [nio-8080-exec-3] o.a.c.authenticator.AuthenticatorBase : Not subject to any constraint
2018-11-25 10:50:12.999 DEBUG 11840 --- [nio-8080-exec-3] org.apache.tomcat.util.http.Parameters : Set encoding to UTF-8
2018-11-25 10:50:12.999 DEBUG 11840 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet : GET "/comunidades", parameters={}
2018-11-25 10:50:12.999 DEBUG 11840 --- [nio-8080-exec-3] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to public org.springframework.http.ResponseEntity<java.lang.String> com.poligran.polifonia.controllers.UsuarioController.autenticar(com.poligran.polifonia.utilities.AuthData)
2018-11-25 10:50:13.000 DEBUG 11840 --- [nio-8080-exec-3] o.j.s.OpenEntityManagerInViewInterceptor : Opening JPA EntityManager in OpenEntityManagerInViewInterceptor
2018-11-25 10:50:13.001 DEBUG 11840 --- [nio-8080-exec-3] m.m.a.RequestResponseBodyMethodProcessor : Read "application/json;charset=UTF-8" to [AUTHDATA - User: null, Password: null]
2018-11-25 10:50:13.003 DEBUG 11840 --- [nio-8080-exec-3] o.s.l.c.support.AbstractContextSource : Got Ldap context on server 'ldap://localhost:12345'
2018-11-25 10:50:13.004 INFO 11840 --- [nio-8080-exec-3] o.s.ldap.core.LdapTemplate : No results found for search, base: ''; filter: '(uid=null)'.
2018-11-25 10:50:13.004 DEBUG 11840 --- [nio-8080-exec-3] .m.m.a.ExceptionHandlerExceptionResolver : Using #ExceptionHandler com.poligran.polifonia.utilities.ErrorMessage com.poligran.polifonia.advices.AuthAdvice.dataNotFoundHandler(com.poligran.polifonia.exceptions.AuthPolifoniaException)
2018-11-25 10:50:13.005 DEBUG 11840 --- [nio-8080-exec-3] m.m.a.RequestResponseBodyMethodProcessor : Using 'application/json', given [*/*] and supported [application/json, application/*+json, application/json, application/*+json]
2018-11-25 10:50:13.005 DEBUG 11840 --- [nio-8080-exec-3] m.m.a.RequestResponseBodyMethodProcessor : Writing [com.poligran.polifonia.utilities.ErrorMessage#6fd9c4ca]
2018-11-25 10:50:13.008 WARN 11840 --- [nio-8080-exec-3] .m.m.a.ExceptionHandlerExceptionResolver : Resolved [com.poligran.polifonia.exceptions.AuthPolifoniaException: Error en la autenticación del usuario]
2018-11-25 10:50:13.008 DEBUG 11840 --- [nio-8080-exec-3] o.j.s.OpenEntityManagerInViewInterceptor : Closing JPA EntityManager in OpenEntityManagerInViewInterceptor
2018-11-25 10:50:13.008 DEBUG 11840 --- [nio-8080-exec-3] o.s.orm.jpa.EntityManagerFactoryUtils : Closing JPA EntityManager
2018-11-25 10:50:13.008 DEBUG 11840 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet : Completed 401 UNAUTHORIZED
2018-11-25 10:50:13.009 DEBUG 11840 --- [nio-8080-exec-3] o.a.tomcat.util.net.SocketWrapperBase : Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper#d601e02:org.apache.tomcat.util.net.NioChannel#75d2ecd0:java.nio.channels.SocketChannel[connected local=/0:0:0:0:0:0:0:1:8080 remote=/0:0:0:0:0:0:0:1:7687]], Read from buffer: [0]
2018-11-25 10:50:13.009 DEBUG 11840 --- [nio-8080-exec-3] org.apache.tomcat.util.net.NioEndpoint : Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper#d601e02:org.apache.tomcat.util.net.NioChannel#75d2ecd0:java.nio.channels.SocketChannel[connected local=/0:0:0:0:0:0:0:1:8080 remote=/0:0:0:0:0:0:0:1:7687]], Read direct from socket: [0]
2018-11-25 10:50:13.009 DEBUG 11840 --- [nio-8080-exec-3] o.apache.coyote.http11.Http11Processor : Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper#d601e02:org.apache.tomcat.util.net.NioChannel#75d2ecd0:java.nio.channels.SocketChannel[connected local=/0:0:0:0:0:0:0:1:8080 remote=/0:0:0:0:0:0:0:1:7687]], Status in: [OPEN_READ], State out: [OPEN]
2018-11-25 10:50:22.583 DEBUG 11840 --- [l-1 housekeeper] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Pool stats (total=10, active=0, idle=10, waiting=0)
Thanks so much for your time.

JpaTransactionManager doesn't rollback transaction

I use JHipster to make a simple app and write a service, code as follows:
#Service
#Transactional
public class OperateQueueActionService {
#Transactional(rollbackFor = Throwable.class)
public OperateQueueDTO apply(OperateQueueDTO operateQueueDTO, QueueEventType queueEventType, String deskNo) {
StateMachine<QueueStatus, QueueEventType> stateMachine = operateQueueActionMachineService.getStateMachine();
try { QueueEventDTO operateQueueEventDTO = operateQueueUtils.saveQueueEvent(operateQueueDTO, queueEventType, deskNo);
......in process will throw RuntimeException.
} finally {
stateMachine.stop();
}
}
}
I want the transaction to rollback and not save queueEvent, but the record is saved in the database. This is the transaction log:
[2018-07-24 12:04:51.861] [XNIO-2 task-6] WARN
o.s.s.l.CompositeStateMachineListener -Error during stateContext
java.lang.RuntimeException: 无效状态 at
com.higoee.queue.state.utils.OperateQueueStateMachineLogListener.stateContext(OperateQueueStateMachineLogListener.java:58)
at java.lang.Thread.run(Thread.java:745) [2018-07-24 12:04:51.871]
[XNIO-2 task-6] INFO c.h.q.s.u.OperateQueueStateMachineLogListener
-4d667539-3316-491d-a0db-240e29b0fcae状态机状态为:STATEMACHINE_STOP [2018-07-24 12:04:51.872] [XNIO-2 task-6] DEBUG
o.s.orm.jpa.JpaTransactionManager -Initiating transaction commit
[2018-07-24 12:04:51.874] [XNIO-2 task-6] DEBUG
o.s.orm.jpa.JpaTransactionManager -Committing JPA transaction on
EntityManager
JPA config have not problem,spring state machine had been catch the exception which was thrown in StateMachineListenerAdapter.

Spring unit test MockMvc fails when using custom filter in Spring Security

I have a web application that should only be callable from specific IP addresses. Other than that, there is no need for authentication or for authorization; if you're coming from the right IP, you can see everything.
To that end, searching StackOverflow and other places, I found a number of suggestions for filtering requests by IP address in Spring Security. They all took this form (extending WebSecurityConfigurerAdapter using java configuration):
http.authorizeRequests().anyRequest().access("hasIpAddress('127.0.0.1/0')");
However, that never worked for me; it never rejected any request, no matter what IP address I made the request from. Instead, I implemented my IP filtering with a custom filter like this:
#Configuration
#EnableWebSecurity
#PropertySource("classpath:config.properties")
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
#Autowired
private Environment env;
#Override
protected void configure(HttpSecurity http) throws Exception {
String ipRange = env.getRequiredProperty("trusted_ips");
logger.info("##### SETTING UP SECURITY CONFIGURATION #############");
logger.info("## trusted_ips: " + ipRange);
logger.info("##### SETTING UP SECURITY CONFIGURATION - END #############");
http.addFilterBefore(new IPSecurityFilter(ipRange), J2eePreAuthenticatedProcessingFilter.class)
.authorizeRequests().antMatchers("/**").permitAll();
}
}
My IPSecurityFilter:
public class IPSecurityFilter extends OncePerRequestFilter {
private static final Logger logger = LoggerFactory.getLogger(IPSecurityFilter.class);
private String[] ipAddresses;
public IPSecurityFilter(String strIPAddresses) {
logger.info("#### Our IP Address whitelist: " + strIPAddresses);
this.ipAddresses = strIPAddresses.split(",");
}
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
logger.info("Checking whether request should be allowed: " + request.getRequestURI());
logger.info("### Request is coming from IP address: " + request.getRemoteAddr());
for (String ipAddress : ipAddresses) {
if (ipAddress.equals(request.getRemoteAddr())) {
logger.info("### Allowing request from ip address: " + request.getRemoteAddr());
return; // We accept requests from this IP address
}
}
// The remote IP address isn't on our white list; throw an exception
throw new AccessDeniedException("Access has been denied for your IP address: " + request.getRemoteAddr());
}
}
This seems to work in that the request is rejected if it originates from an IP Address that isn't on my white list.
However, with this configuration, my unit (using MockMvc) test fails; and it fails in a way that I would never have expected. When the unit test runs, it appears to use the Spring Security configuration correctly and the request passes the security test (the IP white list includes 127.0.0.1 and according to the log that is generated while the test is being run, the request is coming from that IP). However, the request never seems to be routed to my controller.
Here is my test:
#RunWith(SpringRunner.class)
#WebMvcTest()
//#WebMvcTest(value = HandlerController.class)
#AutoConfigureMockMvc
#Import(SecurityConfig.class)
public class HandlerControllerTest {
#Autowired
private MockMvc mvc;
#Test
public void getIndex() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().json("{\"services\":[\"OutboundMessageService\"]}", true));
}
}
And finally, here is my controller (please ignore the idiotic way that I'm generating the JSON return value, it's still very early in development):
#RestController
public class HandlerController {
private static final Logger logger = LoggerFactory.getLogger(HandlerController.class);
#RequestMapping("/")
public String index() {
logger.info("### handling a request for / ###");
return "{\"services\":[\"OutboundMessageService\"]}";
}
}
And here are the test results:
2017-11-14 08:29:12.151 INFO 25412 --- [ main] c.z.s.controllers.HandlerControllerTest : Starting HandlerControllerTest on 597NLL1 with PID 25412 (started by User in C:\Development\KnowledgeBin\NewArchitecture\OutboundMessageHandler)
2017-11-14 08:29:12.152 INFO 25412 --- [ main] c.z.s.controllers.HandlerControllerTest : No active profile set, falling back to default profiles: default
2017-11-14 08:29:12.178 INFO 25412 --- [ main] o.s.w.c.s.GenericWebApplicationContext : Refreshing org.springframework.web.context.support.GenericWebApplicationContext#209da20d: startup date [Tue Nov 14 08:29:12 MST 2017]; root of context hierarchy
2017-11-14 08:29:13.883 INFO 25412 --- [ main] b.a.s.AuthenticationManagerConfiguration :
Using default security password: 56e3fab8-f7fb-4fbd-b2d2-e37eae8cef5e
2017-11-14 08:29:13.962 INFO 25412 --- [ main] c.z.services.security.IPSecurityFilter : #### Our IP Address whitelist: 122.22.22.22,127.0.0.1
2017-11-14 08:29:14.086 INFO 25412 --- [ main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: org.springframework.security.web.util.matcher.AnyRequestMatcher#1, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter#3f4f9acd, org.springframework.security.web.context.SecurityContextPersistenceFilter#470a9030, org.springframework.security.web.header.HeaderWriterFilter#60c16548, org.springframework.security.web.csrf.CsrfFilter#435ce306, org.springframework.security.web.authentication.logout.LogoutFilter#607b2792, com.zpaper.services.security.IPSecurityFilter#46baf579, org.springframework.security.web.savedrequest.RequestCacheAwareFilter#27494e46, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter#36453307, org.springframework.security.web.authentication.AnonymousAuthenticationFilter#4bf324f9, org.springframework.security.web.session.SessionManagementFilter#452c8a40, org.springframework.security.web.access.ExceptionTranslationFilter#39ce27f2, org.springframework.security.web.access.intercept.FilterSecurityInterceptor#5767b2af]
2017-11-14 08:29:14.183 INFO 25412 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/]}" onto public java.lang.String com.zpaper.services.controllers.HandlerController.index()
2017-11-14 08:29:14.184 INFO 25412 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/OutboundMessageService]}" onto public java.lang.String com.zpaper.services.controllers.HandlerController.outboundMessage()
2017-11-14 08:29:14.189 INFO 25412 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2017-11-14 08:29:14.190 INFO 25412 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2017-11-14 08:29:14.243 INFO 25412 --- [ main] c.z.s.config.HandlerWebConfiguration : #### My Configuration handler was called ####
2017-11-14 08:29:14.253 INFO 25412 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler]
2017-11-14 08:29:14.313 INFO 25412 --- [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for #ControllerAdvice: org.springframework.web.context.support.GenericWebApplicationContext#209da20d: startup date [Tue Nov 14 08:29:12 MST 2017]; root of context hierarchy
2017-11-14 08:29:14.784 INFO 25412 --- [ main] o.s.b.t.m.w.SpringBootMockServletContext : Initializing Spring FrameworkServlet ''
2017-11-14 08:29:14.784 INFO 25412 --- [ main] o.s.t.web.servlet.TestDispatcherServlet : FrameworkServlet '': initialization started
2017-11-14 08:29:14.805 INFO 25412 --- [ main] o.s.t.web.servlet.TestDispatcherServlet : FrameworkServlet '': initialization completed in 21 ms
2017-11-14 08:29:14.897 INFO 25412 --- [ main] c.z.s.controllers.HandlerControllerTest : Started HandlerControllerTest in 3.095 seconds (JVM running for 3.995)
2017-11-14 08:29:14.981 INFO 25412 --- [ main] c.z.services.security.IPSecurityFilter : Checking whether request should be allowed: /
2017-11-14 08:29:14.981 INFO 25412 --- [ main] c.z.services.security.IPSecurityFilter : ### Request is coming from IP address: 127.0.0.1
2017-11-14 08:29:14.981 INFO 25412 --- [ main] c.z.services.security.IPSecurityFilter : ### Allowing request from ip address: 127.0.0.1
MockHttpServletRequest:
HTTP Method = GET
Request URI = /
Parameters = {}
Headers = {Accept=[application/json]}
Handler:
Type = null
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {X-Content-Type-Options=[nosniff], X-XSS-Protection=[1; mode=block], Cache-Control=[no-cache, no-store, max-age=0, must-revalidate], Pragma=[no-cache], Expires=[0], X-Frame-Options=[DENY]}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 3.363 sec <<< FAILURE! - in com.zpaper.services.controllers.HandlerControllerTest
getIndex(com.zpaper.services.controllers.HandlerControllerTest) Time elapsed: 0.12 sec <<< ERROR!
org.json.JSONException: Unparsable JSON string:
at org.skyscreamer.jsonassert.JSONParser.parseJSON(JSONParser.java:42)
As can be seen in the log messages, the IP filter is being invoked and is allowing the request to continue. However, the debug string that is being emitted in my handler is nowhere to be seen and the return body is blank. Can anyone tell me why my security filter would prevent MockMvc from having its request successfully routed to my controller?
Final Note: if I use the http.authorizeRequests().anyRequest().access("hasIpAddress('127.0.0.1/0')"); configuration that I first listed or completely get rid of Spring Security by removing my SecurityConfig class, the request is routed successfully to my handler.
I figured out how to make the test work. I was not able to find a single article that answered my question but by taking different suggestions from multiple blog posts, I came up with this which works for me:
#RunWith(SpringRunner.class)
#WebMvcTest(controllers = HandlerController.class)
public class HandlerControllerTest {
private MockMvc mvc;
#Autowired
private WebApplicationContext webApplicationContext;
#Before
public void setUp() {
// mvc = MockMvcBuilders.standaloneSetup(new HandlerController()).build();
mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
#Test
public void getIndex() throws Exception {
mvc.perform(get("/").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().json("{\"services\":[\"OutboundMessageService\"]}", true));
}
#Test
public void getMessageService() throws Exception {
mvc.perform(get("/OutboundMessageService").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().json("{\"status\": \"SUCCESS\"}", true));
}
}
As you can see, I am no longer auto-wiring the MockMvc object and allowing it be automatically set up but am instead setting it up myself in the setUp() method. The commented-out line in the setUp() method works to successfully test my controller also but it doesn't route the request through my Spring Security IP address filter. I'm leaving it in so that users that don't need to test Spring Security can see an alternate method to set up the MockMvc object. The uncommented line sets up a MockMvc object such that it runs the request through both the security filters and my controller.
I know it is late but for others looking for the answer, you can add that filter to the MockMvc object like this:
#Autowired
private MockMvc mvc;
#Autowired
private YourCustomFilter filter;
#Before
public void setUp() {
mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
.addFilter(filter).build();
}

Adding in a Search feature to a code swap challenge

I am participating into a code swap type challenge, for Java and Spring, and I am having some issues adding in a Search feature for this shopping list app. Before I get into depth of code, by search feature I mean search the local database, not something like google. Now I'l show the code and then explain what I'm trying to do underneath it all.
This is the error message:
2016-12-14 10:00:40.476 WARN 10452 --- [ main] o.h.b.i.SessionFactoryBuilderImpl : Unrecognized hbm2ddl_auto value : auto. Supported values include create, create-drop, update, and validate. Ignoring
2016-12-14 10:00:42.300 INFO 10452 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2016-12-14 10:00:46.009 WARN 10452 --- [ main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'shoppingListController': Unsatisfied dependency expressed through field 'shoppingListRepo'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'shoppingListRepository': Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property category found for type ShoppingList!
2016-12-14 10:00:46.014 INFO 10452 --- [ main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2016-12-14 10:00:46.071 INFO 10452 --- [ main] o.apache.catalina.core.StandardService : Stopping service Tomcat
2016-12-14 10:00:46.393 INFO 10452 --- [ main] utoConfigurationReportLoggingInitializer :
Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
2016-12-14 10:00:46.455 ERROR 10452 --- [ main] o.s.boot.SpringApplication : Application startup failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'shoppingListController': Unsatisfied dependency expressed through field 'shoppingListRepo'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'shoppingListRepository': Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property category found for type ShoppingList!
This is the part of the controller I am editing:
#GetMapping("/lists")
public String lists(Model model, #RequestParam(name = "srch-term", required = false) String searchTerm) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String email = auth.getName();
User u = userRepo.findOneByEmail(email);
if (searchTerm == null || "".equals(searchTerm)) {
model.addAttribute("lists", shoppingListRepo.findAllByUser(u));
} else {
ArrayList<ShoppingList> userLists = new ArrayList<ShoppingList>();
ArrayList<ShoppingList> lists = shoppingListRepo.findByCategoryContainsOrNameContainsAllIgnoreCase(searchTerm,
searchTerm);
for (ShoppingList list : lists) {
if (list.getUser() == u) {
userLists.add(list);
}
}
model.addAttribute("lists", shoppingListRepo.findAllByUser(u));
model.addAttribute("user", u);
}
return "lists";
}
This is the controller before being edited by me
#GetMapping("/lists")
public String lists(Model model) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String email = auth.getName();
User u = userRepo.findOneByEmail(email);
model.addAttribute("lists", shoppingListRepo.findAllByUser(u));
model.addAttribute("user", u);
return "lists";
}
This is my Repository
package org.elevenfifty.shoppinglist.repositories;
import java.util.ArrayList;
import org.elevenfifty.shoppinglist.beans.ShoppingList;
import org.elevenfifty.shoppinglist.beans.User;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface ShoppingListRepository extends CrudRepository<ShoppingList, Long> {
ArrayList<ShoppingList> findAllByUser(User u);
ArrayList<ShoppingList> findByCategoryContainsOrNameContainsAllIgnoreCase(String categoryPart, String namePart);
}
Now like I said I am getting a search feature working. I am not sure where the property is in my error message I am hoping some fresh eyes can help find what I am clearly missing.
Add category field and its getters and setters to the ShoppingList class.
private String category
public void setCategory(String category){
this.category = category;
}
public String getCategory(){
return category;
}

Categories