I have a working implementation of Spring Boot with Tomcat that handles fine in a JAR file within a Linux environment. The same code fails to work with Google Cloud. I'm trying to get JPA to work.
Google Cloud prefers Jetty over Tomcat. This may relate to my issue, but I'm not sure how to fix it. I have the default recommended conversion from a standard Spring Boot JAR to a WAR version for Google Cloud's AppEngine. My dependencies work fine if I try them in a pre-set project from the spring.io site. I'm not using databases, so I cut out MySQL, which is default.
My problem relates to a missing EntityManagerFactory. Since I'm trying to keep this post brief, I just include what I think is vital. You can find the essentials to the complete project at: https://github.com/shatterblast/spring-sylveria_fix-search
Basically, I can't bring up the Admin Console for this GCP project. The project and the Admin Console both respond with a 503 from a request. There is no error message during startup, and it executes fine. From tweaking the code, I found the EntityManager bean as the problem itself. Re-naming beans has not helped.
Thank you.
import com.weslange.springboot.sylveria.entity.Gamer;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
#Repository
public class GamerDAOHibernateImpl implements GamerDAO {
private EntityManager entityManager;
#Autowired
public GamerDAOHibernateImpl( EntityManager theEntityManager ) {
entityManager = theEntityManager;
}
#Override
public Gamer findById( int id ) {
Session currentSession = entityManager.unwrap( Session.class );
Gamer gamer = currentSession.get( Gamer.class, id );
return gamer;
}
#Override
public void save( Gamer gamer ) {
Session currentSession = entityManager.unwrap( Session.class );
currentSession.saveOrUpdate( gamer );
}
}
.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
#Repository
public class TokenDAOHibernateImpl implements TokenDAO {
private EntityManager entityManager;
#Autowired
public TokenDAOHibernateImpl(EntityManager theEntityManager) {
entityManager = theEntityManager;
}
}
.
import com.weslange.springboot.sylveria.SylveriaServerApplication;
import com.weslange.springboot.sylveria.entity.Token;
import com.weslange.springboot.sylveria.service.GamerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
#RestController
#RequestMapping( "/" )
public class TokenRestController {
private static final Logger logger = LoggerFactory.getLogger( SylveriaServerApplication.class );
private GamerService gamerService;
#Autowired
public TokenRestController( GamerService gamerService ) {
gamerService = gamerService;
}
#PostMapping( "/" )
public HashMap addEmployee( #RequestBody Token token, HttpServletRequest request ) {
HashMap<String, String> returnMap = new HashMap();
returnMap.put( "sylveriaConnectionSuccess", "true" );
return returnMap;
}
}
Related
Basically, I have created all of the pojo and layers(including the repository layer) necessary for Spring Boot to automatically implement MySql commands. When I trying to run the programme, I get the following command:
Description:
Parameter 0 of constructor in com.fsse2207.project_backend.api.ProductApi required a bean of type 'com.fsse2207.project_backend.service.ProductService' that could not be found.
Action:
Consider defining a bean of type 'com.fsse2207.project_backend.service.ProductService' in your configuration.
It turns out there's sth wrong about the bean in my ProductApi. It says "
Could not autowire. No beans of 'ProductService' type found." How do I fix it?
The following is the interface under the service layer:
package com.fsse2207.project_backend.service;
import com.fsse2207.project_backend.data.ProductCreateData;
import com.fsse2207.project_backend.data.ProductDetailData;
import com.fsse2207.project_backend.exception.ProductFoundByIdException;
import org.springframework.stereotype.Service;
public interface ProductService {
ProductDetailData createProductData (ProductCreateData productCreateData) throws ProductFoundByIdException;
}
The following is the service class:
package com.fsse2207.project_backend.service.impl;
import com.fsse2207.project_backend.data.ProductCreateData;
import com.fsse2207.project_backend.data.ProductDetailData;
import com.fsse2207.project_backend.data.entity.ProductEntity;
import com.fsse2207.project_backend.exception.ProductFoundByIdException;
import com.fsse2207.project_backend.repository.ProductRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class ProductServiceImpl {
private ProductRepository productRepository;
#Autowired
public ProductServiceImpl(ProductRepository productRepository){
this.productRepository=productRepository;
}
public ProductDetailData createProductData (ProductCreateData productCreateData) throws ProductFoundByIdException {
ProductEntity productEntity=new ProductEntity(productCreateData);
if(productRepository.existsById(productEntity.getpId())){
throw new ProductFoundByIdException();
}
return new ProductDetailData(productRepository.save(productEntity));
}
}
The following is the Api:
package com.fsse2207.project_backend.api;
import com.fsse2207.project_backend.data.ProductCreateData;
import com.fsse2207.project_backend.data.ProductDetailData;
import com.fsse2207.project_backend.data.dto.CreateRequestDto;
import com.fsse2207.project_backend.data.dto.CreateResponseDto;
import com.fsse2207.project_backend.exception.ProductFoundByIdException;
import com.fsse2207.project_backend.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class ProductApi {
private ProductService productService;
#Autowired
public ProductApi(ProductService productService){
this.productService=productService;
}
#PostMapping
public CreateResponseDto createResponseDto(#RequestBody CreateRequestDto createRequestDto) throws ProductFoundByIdException {
ProductCreateData productCreateData=new ProductCreateData(createRequestDto);
ProductDetailData productDetailData =productService.createProductData(productCreateData);
return new CreateResponseDto(productDetailData);
}
}
I found the problem:
I didn't add the implements keyword in the class definition of ProductServiceImpl so it was not connected to the bean, aka the interface, aka the service layer.
First of all you should not add annotation #Service for ProductService interface.
Moreover this can happen when you have your Class Application in "another package".
You can solve the problem using annotation #ComponentScan (basePackages = {"your.company.domain.package"})
Whenever I start a spring boot project I keep getting this error, This question has been asked multiple times on stakeoverflow I have tried all the solutions but nothing works for me. My first questions are what is the reason for this error, and how can I fix it.
FilterApplication.java
package com.example.filter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication()
public class FilterApplication {
public static void main(String[] args) {
SpringApplication.run(FilterApplication.class, args);
}
}
FilterConnector.java
package com.example.filter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
#RestController
public class FilterConnector {
#Autowired
private FilterService filterService;
#GetMapping("/home")
public List<Filter> home()
{
return this.filterService.getData();
}
}
FilterService.java
package com.example.filter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
#Service
public class FilterService {
#Autowired
private FilterDao filterDao;
public List<Filter> getData() {
System.out.println("----------------------HERE-------------");
return this.filterDao.findAll();
}
}
FilterDao.java
package com.example.filter;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface FilterDao extends JpaRepository<Filter, Integer> {
}
Spring framework relies on ApplicationContext to inject dependencies into the dependent object. For example your FilterDao will be inject into FilterService object.
To do this Spring will try to initialized instances of these classes at the start of the Application, but if it fails you will see this error message.
The problem with your code is related to FilterDao class, Spring can't initialize an instance of this class because it requires the Database to be configured correctly.
To fix this error:
you need to check your database connection is correct.
make sure there is a table corresponding to Filter class.
check the primary key (ID) is actually of type Integer.
If you provide full error stack I can give you a specific solution.
Note:
The issues is not related to FilterService or FilterConnector, because you are using #Autowired annotation implying the dependencies are optional and they will be injected after the bean initialization.
The project is being migrated from a mix of spring and jersey to full spring boot webflux
The actual error message is:
Type org.glassfish.jersey.servlet.ServletContainer not present
Problem is I don't know why the test is trying to spawn this context, and debugging is extremely hard.
The test declaration is:
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.reactive.function.client.ExchangeStrategies;
import org.springframework.web.reactive.function.client.WebClient;
#ExtendWith(SpringExtension.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#AutoConfigureWebTestClient
#TestPropertySource(properties = {"opentracing.sample-rate=1"})
class ReactiveControllerIT {
#LocalServerPort
int port;
#Autowired
private WebTestClient webClient;
And the application class
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.neo4j.repository.config.EnableReactiveNeo4jRepositories;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
#SpringBootApplication
#EnableScheduling
#EnableReactiveNeo4jRepositories
#EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class SeoGraphApplication {
public static void main(String[] args) {
SpringApplication.run(SeoGraphApplication.class, args);
}
}
Even with empty test methods I don't reach the actual method.
Any thoughts?
Thanks,
Omer.
Found it, after many hours of debugging.
this method was the key to the solution:
private WebApplicationType deduceWebApplicationType() {
if (ClassUtils.isPresent(REACTIVE_WEB_ENVIRONMENT_CLASS, null)
&& !ClassUtils.isPresent(MVC_WEB_ENVIRONMENT_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_WEB_ENVIRONMENT_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
for (String className : WEB_ENVIRONMENT_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET;
}
The if regarding the Jersey web environment resulted in true, which eventually made this method return servlet type.
The source of it was usage of error types library in my company which for some odd reason depends on jersey-server and when found, results in a servlet context initialization.
I contacted the authors about it, and worst part is that excluding the server dependency had no effect on the functionality.
Thanks to anyone who spent time on this one.
I am having trouble attaching a ContainerRequstFilter to a very simple JAX-RS rest application inside Glassfish4.
I believe that I've followed the instructions from both the javadoc and various other tutorial sources, but I am now at a complete loss.
The entire source (very short) is below, with the expected functionality:
(login) A user can log in at http://localhost/app/api/login/uname/password and the response is "You are logged in, uname"
(verify) User visits http://localhost/app/api/login/verify/uname and the response is a 401 unauthorized.
The second bit is meant the be implemented as a filter. What actually happens is that the first bit (login) works, and the second bit (verify) completely ignores the filter (including nothing in the logs to indicate that the filter ran). That is, the output is just "Every thing is fine, uname", rather than a 401 error.
What I want to understand is the way to get the filter attached to the verify action. For reference
I'm running glassfish 4.1 build 13
I'm compiling and deploying using gradle, with the deployment action
assassin deploy --force --contextroot /app /path/to/app.war
Glassfish reports that it's using Jersey 2.10.4
Here is the entirety of the source related to the application:
RestApp.java
package test.pack;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("/api")
public class RestApp extends Application
{
#Override
public Set<Class<?>> getClasses()
{
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(Login.class);
return classes;
}
}
Login.java
package test.pack;
import javax.ejb.Stateless;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
#Stateless
#Path("login/")
#Produces("text/json")
public class Login
{
#GET
#Path("{username}/{password}")
public Response login(#PathParam("username") String username, #PathParam("password") String password)
{
System.out.println("Logging in");
return Response.ok("You are logged in, " + username).build();
}
#GET
#Path("/verify/{username}")
#Secured
public Response verify(#PathParam("username") String username)
{
System.out.println("Verify");
return Response.ok("Everything is fine, " + username).build();
}
Secured.java
package test.pack;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.ws.rs.NameBinding;
#NameBinding
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.TYPE, ElementType.METHOD})
public #interface Secured
{
}
LoggedInFilter.java
package test.pack;
import java.io.IOException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.Response;
#Secured
public class LoggedInFilter implements ContainerRequestFilter
{
#Override
public void filter(ContainerRequestContext requestContext) throws IOException
{
System.out.println("request");
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
}
}
Ugh. That's embarrassing.
The next tutorial I visited had the solution, which was to register the filter in the RestApp class.
RestApp.java
#ApplicationPath("/api")
public class RestApp extends Application
{
#Override
public Set<Class<?>> getClasses()
{
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(Login.class);
return classes;
}
#Override
public Set<Object> getSingletons()
{
Set<Object> singletons = new HashSet<Object>();
singletons.add(new LoggedInFilter());
return singletons;
}
}
I'll leave the answer here rather than deleting the question, since it was only in one of 4 tutorials that I read, and so this might be at least a little interesting.
I am working on Spring and hibernate project. For database communication we have conventional two layered implementation (i.e DAO layer and Service layer). I have following files:
DemoDao.java
package net.dao;
import java.util.List;
import net.domain.Demo;
public interface DemoDao
{
public List<Demo> get();
}
DemoDaoImpl.java
package net.dao;
import java.util.List;
import net.domain.Demo;
import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
#Repository
public class DemoDaoImpl implements DemoDao
{
#Autowired
SessionFactory sessionFactory;
public List<Demo> get()
{
Session session=sessionFactory.openSession();
List<Demo> list=session.createQuery("from Demo").list();
session.close();
return list;
}
}
That was DAO layer
Follwing is from service layer:
DemoManager.java
package net.service;
import java.util.List;
import net.domain.Demo;
public interface DemoManager
{
public List<Demo> get();
}
DemoManagerImpl.java
package net.service;
import java.util.List;
import net.dao.DemoDao;
import net.domain.Demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class DemoManagerImpl implements DemoManager
{
#Autowired
DemoDao demoDao;
public List<Demo> get()
{
List<Demo> list=demoDao.get();
return list;
}
}
Follwing is my controller
FromDualLayerView.java
package net.spring;
import java.util.List;
import net.domain.Demo;
import net.service.DemoManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class FromDualLayerView
{
#Autowired
DemoManager demoManager;
#RequestMapping("/dualLayer")
public ModelAndView toResult(ModelMap map)
{
List<Demo> list=demoManager.get();
map.addAttribute("listData", list);
return new ModelAndView("result");
}
}
My Question
Actually everything works fine, but my question over here is that i am not annotating the DemoDao and DemoManager interface, but i am autowiring them. According to the autowiring definition the entities which are annotated are injected.
The how come the dependency is injected by Spring container?
And how does it work like an Impl class?
Thanks in advance.
DemoManagerImpl is annotated as a service and is the only qualifying bean to be injected in the FromDualLayerView class, as it's the only component which is instance of DemoManager. I suppose you have the component scan turned on as well.
The #Repository annotation and the #Service annotation mean you are annotating them. It's actually a spring best practice to annotate the implementations and not the interfaces.
Your spring config file is scanning the classpath, thus those beans are detected. Turn spring logging up to TRACE and you'll probably see output along the lines of:
"scanning classpath, found target DemoDaoImpl"