Can't get dropwizard app to work with swagger-ui - dropwizard

I'm having a hard time getting Swagger UI to work with my dropwizard application. The annotated dropwizard app seems to generate the correct json documents but swagger UI is unabel to navigate it properly.
Main API page, generated at http://localhost:8080/v1/TimeService/api-docs:
{"apiVersion":"0.0","swaggerVersion":"1.2","apis":[{"path":"/times"}]}
Swagger displays that page correctly.
Detail information for the time resource generated at http://localhost:8080/v1/TimeService/api-docs/times:
{"apiVersion":"0.0","swaggerVersion":"1.2","basePath":"/v1/TimeService/*","resourcePath":"/times","produces":["application/json"],"apis":[{"path":"/times/","operations":[{"method":"GET","summary":"Retrieves time for given","notes":"timezone parameter is optional, defaults to GMT","type":"array","items":{"$ref":"Time"},"nickname":"getTime","parameters":[{"name":"timezone","description":"timezone","required":false,"items":{"type":"string"},"paramType":"query","allowMultiple":false}]}]}],"models":{"Time":{"id":"Time","properties":{"time":{"type":"string"}}}}}
Which looks good to me. But whenever, in the swagger UI, I click on any "times" hyperlink to display the details, nothing happens. It looks like swagger ui cannot resolve the link correctly.
My annotated resource, TimeResource.java:
package com.cgi.saas.bluprint;
import com.google.common.base.Optional;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiParam;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
#Path("/times")
#Produces(MediaType.APPLICATION_JSON)
#Api("/times")
public class TimeResource {
private final String defaultTimezone;
public TimeResource(String defaultTimezone) {
this.defaultTimezone = defaultTimezone;
}
#GET
#ApiOperation(value = "Retrieves time for given",
notes = "timezone parameter is optional, defaults to GMT",
response = Time.class,
responseContainer = "List")
#Path("/")
public Time getTime(#ApiParam(value="timezone") #QueryParam("timezone") Optional<String> timezone) {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
TimeZone timeZone = TimeZone.getTimeZone(timezone.or(defaultTimezone));
formatter.setTimeZone(timeZone);
String formatted = formatter.format(new Date());
return new Time(formatted);
}
}
The main service class, TimeService.java:
package com.cgi.saas.bluprint;
import java.util.EnumSet;
import javax.servlet.DispatcherType;
import javax.servlet.FilterRegistration.Dynamic;
import org.eclipse.jetty.servlets.CrossOriginFilter;
import com.wordnik.swagger.config.ConfigFactory;
import com.wordnik.swagger.config.ScannerFactory;
import com.wordnik.swagger.config.SwaggerConfig;
import com.wordnik.swagger.jaxrs.config.DefaultJaxrsScanner;
import com.wordnik.swagger.jaxrs.listing.ApiDeclarationProvider;
import com.wordnik.swagger.jaxrs.listing.ApiListingResourceJSON;
import com.wordnik.swagger.jaxrs.listing.ResourceListingProvider;
import com.wordnik.swagger.jaxrs.reader.DefaultJaxrsApiReader;
import com.wordnik.swagger.reader.ClassReaders;
import io.dropwizard.Application;
import io.dropwizard.assets.AssetsBundle;
import io.dropwizard.server.DefaultServerFactory;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
public class TimeService extends Application<TimezoneConfiguration> {
private void configureCors(Environment environment) {
final Dynamic filter = environment.servlets().addFilter("CORS",
CrossOriginFilter.class);
filter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, "/*");
filter.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "GET,PUT,POST,DELETE,OPTIONS");
filter.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*");
filter.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, "*");
filter.setInitParameter("allowedHeaders",
"Content-Type,Authorization,X-Requested-With,Content-Length,Accept,Origin");
filter.setInitParameter("allowCredentials", "true");
}
public static void main(String[] args) throws Exception {
new TimeService().run(args);
}
public void initialize(Bootstrap<TimezoneConfiguration> timezoneConfigurationBootstrap) {
timezoneConfigurationBootstrap.addBundle(new AssetsBundle("/assets/", "/", "index.html"));
timezoneConfigurationBootstrap.addBundle(new AssetsBundle("/assets/swagger", "/swagger", "index.html", "swagger"));
}
#Override
public void run(TimezoneConfiguration appConfig, Environment environment) throws Exception {
DefaultServerFactory sf = (DefaultServerFactory) appConfig.getServerFactory();
String rootPath = "/v1/" + appConfig.getDeployName() + "/*";
sf.setJerseyRootPath(rootPath);
configureCors(environment);
String defaultTimezone = appConfig.getDefaultTimezone();
TimeResource timeResource = new TimeResource(defaultTimezone);
environment.jersey().register(timeResource);
// Swagger Resource
environment.jersey().register(new ApiListingResourceJSON());
// Swagger providers
environment.jersey().register(new ApiDeclarationProvider());
environment.jersey().register(new ResourceListingProvider());
// Swagger Scanner, which finds all the resources for #Api Annotations
ScannerFactory.setScanner(new DefaultJaxrsScanner());
// Add the reader, which scans the resources and extracts the resource information
ClassReaders.setReader(new DefaultJaxrsApiReader());
// Set the swaggeonfigurationBootstrap
final SwaggerConfig swConfig = ConfigFactory.config();
swConfig.setBasePath(rootPath);
}
}
My 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.cgi.saas.bluprint</groupId>
<artifactId>Application2</artifactId>
<version>1.0</version>
<repositories>
<repository>
<id>sonatype-nexus-snapshots</id>
<name>Sonatype Nexus Snapshots</name>
<url>http://oss.sonatype.org/content/repositories/snapshots</url>
</repository>
</repositories>
<properties>
<dropwizard.version>0.9.0-SNAPSHOT</dropwizard.version>
</properties>
<dependencies>
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-core</artifactId>
<version>${dropwizard.version}</version>
</dependency>
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-assets</artifactId>
<version>${dropwizard.version}</version>
</dependency>
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-jersey</artifactId>
<version>${dropwizard.version}</version>
</dependency>
<dependency>
<groupId>com.wordnik</groupId>
<artifactId>swagger-jaxrs_2.10</artifactId>
<version>1.3.10</version>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-scala_2.10</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.wordnik</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.3.10</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.2</version>
<configuration>
<createDependencyReducedPom>true</createDependencyReducedPom>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.cgi.saas.bluprint.TimeService</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

Rewrote it as follows:
Cloned the latest and greatest version of swagger-ui at https://github.com/swagger-api/swagger-ui.git
Copied dist under src/main/resources/swagger/assets
Updated pom.xml:
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-core</artifactId>
<version>${dropwizard.version}</version>
</dependency>
<dependency>
<groupId>io.federecio</groupId>
<artifactId>dropwizard-swagger</artifactId>
<version>0.6</version>
</dependency>
Updated TimeService.java:
import java.util.EnumSet;
import javax.servlet.DispatcherType;
import javax.servlet.FilterRegistration.Dynamic;
import org.eclipse.jetty.servlets.CrossOriginFilter;
import io.dropwizard.Application;
import io.dropwizard.server.DefaultServerFactory;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
import io.federecio.dropwizard.swagger.SwaggerDropwizard;
public class TimeService extends Application<TimezoneConfiguration> {
private final SwaggerDropwizard swaggerDropwizard = new SwaggerDropwizard();
private void configureCors(Environment environment) {
final Dynamic filter = environment.servlets().addFilter("CORS",
CrossOriginFilter.class);
filter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, "/*");
filter.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "GET,PUT,POST,DELETE,OPTIONS");
filter.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*");
filter.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, "*");
filter.setInitParameter("allowedHeaders",
"Content-Type,Authorization,X-Requested-With,Content-Length,Accept,Origin");
filter.setInitParameter("allowCredentials", "true");
}
public static void main(String[] args) throws Exception {
new TimeService().run(args);
}
public void initialize(Bootstrap<TimezoneConfiguration> timezoneConfigurationBootstrap) {
swaggerDropwizard.onInitialize(timezoneConfigurationBootstrap);
}
#Override
public void run(TimezoneConfiguration appConfig, Environment environment) throws Exception {
DefaultServerFactory sf = (DefaultServerFactory) appConfig.getServerFactory();
String rootPath = "/v1/" + appConfig.getDeployName() + "/*";
sf.setJerseyRootPath(rootPath);
configureCors(environment);
String defaultTimezone = appConfig.getDefaultTimezone();
TimeResource timeResource = new TimeResource(defaultTimezone);
environment.jersey().register(timeResource);
swaggerDropwizard.onRun(appConfig, environment, "localhost");
}
}
The swagger ui is available at http://localhost:8080/v1/TimeService/swagger

Related

Using #Inject in a Jersey Servlet, for implementing Auth, Auth filter to pass a User object, giving UnsatisfiedDependencyException

I am following the guide: Best practice for REST token-based authentication with JAX-RS and Jersey, for implementing an Authentication and Authorization filter for my RestAPI. I am getting this one error:
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=User,parent=AuthorizationFilter,qualifiers={#nl.utwente.di.team26.Security.Authentication.User.AuthenticatedUser()},position=-1,optional=false,self=false,unqualified=null,1372104990)
at org.jvnet.hk2.internal.ThreeThirtyResolver.resolve(ThreeThirtyResolver.java:51)
at org.jvnet.hk2.internal.ClazzCreator.resolve(ClazzCreator.java:188)
at org.jvnet.hk2.internal.ClazzCreator.resolveAllDependencies(ClazzCreator.java:211)
at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:334)
at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:463)
at org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:59)
at org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:47)
at org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture$1.call(Cache.java:74)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture.run(Cache.java:131)
at org.glassfish.hk2.utilities.cache.Cache.compute(Cache.java:176)
at org.jvnet.hk2.internal.SingletonContext.findOrCreate(SingletonContext.java:98)
at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2102)
at org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:93)
at org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:67)
at org.glassfish.jersey.inject.hk2.AbstractHk2InjectionManager.lambda$getAllServiceHolders$0(AbstractHk2InjectionManager.java:136)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.LinkedList$LLSpliterator.forEachRemaining(LinkedList.java:1239)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
at org.glassfish.jersey.inject.hk2.AbstractHk2InjectionManager.getAllServiceHolders(AbstractHk2InjectionManager.java:140)
at org.glassfish.jersey.inject.hk2.ImmediateHk2InjectionManager.getAllServiceHolders(ImmediateHk2InjectionManager.java:30)
at org.glassfish.jersey.internal.inject.Providers.getServiceHolders(Providers.java:299)
at org.glassfish.jersey.internal.inject.Providers.getAllRankedProviders(Providers.java:182)
at org.glassfish.jersey.server.ProcessingProvidersConfigurator.postInit(ProcessingProvidersConfigurator.java:95)
at org.glassfish.jersey.server.ApplicationHandler.lambda$initialize$2(ApplicationHandler.java:349)
at java.base/java.util.Arrays$ArrayList.forEach(Arrays.java:4411)
at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:349)
at org.glassfish.jersey.server.ApplicationHandler.lambda$initialize$1(ApplicationHandler.java:293)
In essence:
There is an authentication endpoint which checks the login credentials.
It issues a token/cookie as a response, and is all good, (until I implemented the injection part)
So when the makes a request the request is first inspected by this Authentication Filter:
#Secured
#Provider
#Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {
#Inject
#AuthenticatedUser
Event<String> userAuthenticatedEvent;
#Context
UriInfo uriInfo;
String userId;
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
Map<String, Cookie> cookieJar = requestContext.getCookies();
// Validate the Cookie Token
try {
if (!hasCookie(cookieJar)) {
sendToLogin(requestContext);
} else {
// Extract the token from the Cookie
String token = cookieJar.get(CONSTANTS.COOKIENAME).getValue();
try {
// Validate the token
validateToken(token);
userAuthenticatedEvent.fire(userId);
} catch (TokenObsoleteException e) {
e.printStackTrace();
sendToLogin(requestContext);
} catch (AuthenticationDeniedException e) {
e.printStackTrace();
abortWithUnauthorized(requestContext);
}
}
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
private boolean hasCookie(Map<String, Cookie> cookieJar) {
// Check if the Authorization header is valid
// It must not be null and must be prefixed with "Bearer" plus a whitespace
// The authentication scheme comparison must be case-insensitive
return cookieJar.containsKey(CONSTANTS.COOKIENAME);
}
private void sendToLogin(ContainerRequestContext requestContext) throws URISyntaxException {
requestContext.abortWith(Response.seeOther(new URI("http://localhost:8080/apiName/")).build());
}
private void abortWithUnauthorized(ContainerRequestContext requestContext) {
// Abort the filter chain with a 401 status code response
requestContext.abortWith(
Response.status(Response.Status.UNAUTHORIZED).build());
}
private void validateToken(String token) throws AuthenticationDeniedException, TokenObsoleteException {
// Check if the token was issued by the server and if it's not expired
// Throw an Exception if the token is invalid
}
public static Claims decodeJWT(String jwt) {
}
}
This filter fires an event such that an Authenticated user can be created.
#RequestScoped
public class AuthenticatedUserProducer {
#Produces
#RequestScoped
#AuthenticatedUser
private User authenticatedUser;
UserDao userDao = new UserDao();
#RequestScoped
public void handleAuthenticationEvent(#Observes #AuthenticatedUser String userId) {
int user = Integer.parseInt(userId);
this.authenticatedUser = findUser(user);
}
private User findUser(int userId) {
User user = null;
// Hit the the database or a service to find a user by its username and return it
// Return the User instance
return user;
}
}
This should produce a User instance, under variable name AuthenticatedUser.
But, when the same code is called for checking User Roles, in the Authorization filter, the error above is shown:
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=User,parent=AuthorizationFilter,qualifiers={#nl.utwente.di.team26.Security.Authentication.User.AuthenticatedUser()},position=-1,optional=false,self=false,unqualified=null,1372104990)
The Authorization Filter is:
#Secured
#Provider
#Priority(Priorities.AUTHORIZATION)
public class AuthorizationFilter implements ContainerRequestFilter {
#Context
private ResourceInfo resourceInfo;
#Inject
#AuthenticatedUser
User authenticatedUser; //<--This is where the error comes from.
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
// Get the resource class which matches with the requested URL
// Extract the roles declared by it
Class<?> resourceClass = resourceInfo.getResourceClass();
List<Role> classRoles = extractRoles(resourceClass);
// Get the resource method which matches with the requested URL
// Extract the roles declared by it
Method resourceMethod = resourceInfo.getResourceMethod();
List<Role> methodRoles = extractRoles(resourceMethod);
try {
// Check if the user is allowed to execute the method
// The method annotations override the class annotations
if (methodRoles.isEmpty()) {
checkPermissions(classRoles);
} else {
checkPermissions(methodRoles);
}
} catch (NotAuthorizedException e) {
requestContext.abortWith(
Response.status(Response.Status.FORBIDDEN).build());
}
}
// Extract the roles from the annotated element
private List<Role> extractRoles(AnnotatedElement annotatedElement) {
if (annotatedElement == null) {
return new ArrayList<>();
} else {
Secured secured = annotatedElement.getAnnotation(Secured.class);
if (secured == null) {
return new ArrayList<>();
} else {
Role[] allowedRoles = secured.value();
return Arrays.asList(allowedRoles);
}
}
}
private void checkPermissions(List<Role> allowedRoles) throws NotAuthorizedException {
// Check if the user contains one of the allowed roles
// Throw an Exception if the user has not permission to execute the method
if (authenticatedUser.getClarificationLevel() < allowedRoles.get(0).ordinal()) {
throw new NotAuthorizedException("You shall not pass!");
}
}
}
Some other code:
#Secured Annotation
#NameBinding
#Retention(RUNTIME)
#Target({TYPE, METHOD})
public #interface Secured {
Role[] value() default {};
}
Authenticated User Annotation
#Qualifier
#Retention(RUNTIME)
#Target({ METHOD, FIELD, PARAMETER })
public #interface AuthenticatedUser { }
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<welcome-file-list>
<welcome-file>login.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
POM
<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>nl.utwente.di.app</groupId>
<artifactId>app</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>11</release>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<filteringDeploymentDescriptors>true</filteringDeploymentDescriptors>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.6.1</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.6.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.containers/jersey-container-servlet -->
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.30.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.30.1</version>
</dependency>
<!-- Required only when you are using JAX-RS Client -->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.30.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.media/jersey-media-json-jackson -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.29.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/jakarta.xml.bind/jakarta.xml.bind-api -->
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>2.3.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish.jaxb/jaxb-runtime -->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple -->
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.12</version>
</dependency>
<!-- For the cookie things-->
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>2.0.SP1</version>
</dependency>
<!-- For the token things -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.1</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId> <!-- or jjwt-gson if Gson is preferred -->
<version>0.11.1</version>
<scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.containers.glassfish/jersey-gf-cdi -->
<dependency>
<groupId>org.glassfish.jersey.containers.glassfish</groupId>
<artifactId>jersey-gf-cdi</artifactId>
<version>2.14</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
I have a beans.xml after searching a bit this was recommended, but I am not sure how it works.
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="all">
</beans>
Other things I have read:
Creation of bindings (not sure how this would be implemented)
Something to do with a lot of config files.
I am not using SpringBoot or other fancy things. Only simple Jax-rs, Jersey 2.30.1 and some things regarding tokens like jwt.
By reading the error, it seems only that the injected User is not present, so the program has nothing there to inject, but if the class is present why id the DependencyUnsatisfied?
Have I defined the injection properly?
Have I defined the name bindings properly?
Have I used the right maven imports?
Can anyone help? Feel free to ask any further questions.
Thanks.

why can't I redirect after successful login?

I am trying to access a welcome page after login using
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService customUserDetailsService;
#Autowired
private DataSource dataSource;
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/resources/**").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.successForwardUrl("/welcome")
.permitAll()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/");
}
}
My UserDetailsService is:
#Service(value = "customUserDetailsService")
public class CustomUserDetailsServiceImpl implements UserDetailsService {
private static Logger logger = LoggerFactory.getLogger(CustomUserDetailsServiceImpl.class);
#Autowired
private UserService userService;
#Override
#Transactional(readOnly = true)
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
User user = userService.findByEmail(email);
if (user == null) {
logger.error("User with email" + email + " not found.");
throw new UsernameNotFoundException("Oops! User not found with username: " + email);
} else {
logger.info("User {} successfully logged", user.getUsername());
return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPassword(), getAuthorities(user));
}
}
private Collection<GrantedAuthority> getAuthorities(User user) {
List<GrantedAuthority> authorities = new ArrayList<>();
for (UserProfile userProfile : user.getUserProfileSet()) {
authorities.add(new SimpleGrantedAuthority("ROLE_" + userProfile.getType()));
}
return authorities;
}
}
The relevant bits of the controllers are:
#RequestMapping(value = "/", method = RequestMethod.GET)
public String index(Principal principal) {
if (logger.isDebugEnabled()) {
logger.debug("getWelcome is executed");
System.out.println(principal);
}
return principal == null ? "homeNotSignedIn" : "welcome";
}
#GetMapping("/login")
public String login(Model model, String error, String logout) {
if (error != null)
model.addAttribute("error", "Your username and password is invalid.");
if (logout != null)
System.out.println(">>>>>>>>>>>>>>>>>>> LOGOUT <<<<<<<<<<<<<<<<<<");
model.addAttribute("message", "You have been logged out successfully.");
return "login";
}
#GetMapping("/welcome")
public String welcome(Model model) {
System.out.println(">>>>>>>>>>>>>>>>>>>>>>> WELCOME <<<<<<<<<<<<<<<<<<<<<<<");
return "welcome";
}
My pom.xml is:
<?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>ie.gtludwig.pa</groupId>
<artifactId>pa</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>PA</name>
<modules>
<module>core</module>
<module>engine</module>
</modules>
<properties>
<!-- JAVA -->
<version.java>1.8</version.java>
<java.version>${version.java}</java.version>
<jdk.version>${version.java}</jdk.version>
<maven.compiler.target>${version.java}</maven.compiler.target>
<maven.compiler.source>${version.java}</maven.compiler.source>
<!-- Generic properties -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- External Dependency Versions -->
<spring-boot.version>2.1.3.RELEASE</spring-boot.version>
<jedis.version>2.9.1</jedis.version>
<junit.version>4.12</junit.version>
<logback.version>1.2.3</logback.version>
<thymeleaf.version>3.0.11.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.3.0</thymeleaf-layout-dialect.version>
<flyway.version>5.2.0</flyway.version>
<mysql.version>8.0.16</mysql.version>
<h2database.version>1.4.199</h2database.version>
<sendgrid-java.version>4.3.0</sendgrid-java.version>
<commons-lang3.version>3.7</commons-lang3.version>
<commons-io.version>2.6</commons-io.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
<!--WEB-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
<version>${thymeleaf-layout-dialect.version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
<!--SECURITY-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--OPERATIONS-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.jolokia</groupId>
<artifactId>jolokia-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!--SERVER-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<!--DATABASE-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
<scope>runtime</scope>
</dependency>
<!--TEST DATABASE FOR TESTING PROCESSES AND RULES IN-MEMORY-->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2database.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.2.17.Final</version>
<scope>runtime</scope>
</dependency>
<!--EMAIL-->
<!-- https://mvnrepository.com/artifact/com.sendgrid/sendgrid-java -->
<dependency>
<groupId>com.sendgrid</groupId>
<artifactId>sendgrid-java</artifactId>
<version>${sendgrid-java.version}</version>
</dependency>
<!--DEV/TEST-->
<!--DEV TOOLS CONFLICT WITH JREBEL - DISABLE THIS IF JREBEL IS BEING USED -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</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>
<version>5.0.7.RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<!-- Resource plugin to enable expanding properties from this file so that they can be exposed by the zone (E.g. #project.version#) -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<nonFilteredFileExtensions>
<!--font/binary files must be excluded from filtering or they will be corrupted-->
<nonFilteredFileExtension>woff2</nonFilteredFileExtension>
<nonFilteredFileExtension>woff</nonFilteredFileExtension>
<nonFilteredFileExtension>ttf</nonFilteredFileExtension>
<nonFilteredFileExtension>jks</nonFilteredFileExtension>
</nonFilteredFileExtensions>
<delimiters>
<delimiter>#</delimiter>
</delimiters>
<useDefaultDelimiters>false</useDefaultDelimiters>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<!-- Add our project version to the manifest file -->
<version>${project.version}</version>
<description>${project.description}</description>
</manifestEntries>
</archive>
<failOnMissingWebXml>false</failOnMissingWebXml>
<attachClasses>false</attachClasses>
</configuration>
<version>3.1.0</version>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>external</id>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>${spring-boot.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</profile>
</profiles>
What happens is:
When I access localhost:8080/core I get the correct homeNotSignedIn page, but there is no CSS or JS loaded from /resources/**.
I click a login redirection link to the login page (again without CSS or JS) and CAN login.
The logged username is displayed to the console, so the customUserDetailsService seems to be working alright, but I don't get redirected to /welcome.
At this point, I can only logout by typing /logout to the URL and it works and sends me to homeNotSignedIn.
I have been going back and forth at this and I can't seem to get it done.
What am I missing?
I have been going back and forth at this and I can't seem to get it done.
What am I missing?
EDIT
I managed to load CSS and JS by changing:
.antMatchers("/resources/**").permitAll()
to:
.antMatchers("/css/**", "/js/**").permitAll()
When you are using successForwardUrl you will be forwarded to the given URL, but not redirected.
That means that the URL in your browser will not change, however it will display the HTML in your welcome.html.
If you would like to redirect, you can use defaultSuccessUrl as mentioned on the spring-security documentation.
Then your security configuration would look like this.
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/resources/**").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/welcome", true)
.permitAll()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/");
}

Unable to connect to cassandra from Docker container using spring-data-cassandra: NoHostAvailableException: All host(s) tried for query failed

I am using spring-data-cassandra to connect to our cassandra db which is in aws cluster. Using CassandraTemplate I am able to connect locally and get the data but while deploying application in docker container I am getting below error
UnsatisfiedDependencyException: Error creating bean with name 'cassandraTemplate' defined in class path resource
[org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfiguration.class]:
Unsatisfied dependency expressed through method 'cassandraTemplate' parameter 0;
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'session' defined in class path resource [utils/CassandraConfig.class]:
Invocation of init method failed; nested exception is com.datastax.driver.core.exceptions.NoHostAvailableException: All host(s) tried for query failed
(tried: /IP:9042 (com.datastax.driver.core.TransportException: [/IP:9042] Error writing))
Here is my 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">
<parent>
<artifactId>mus-cassadra-read</artifactId>
<groupId>com.rogs.mus</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.rogs.mus</groupId>
<artifactId>external-endpoints</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
<version>1.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.rogs.mus</groupId>
<artifactId>model-cassadra-read</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
<version>1.3.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
<version>1.2.0.RELEASE</version>
</dependency>
<!-- cassandra dependency -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-cassandra</artifactId>
<version>1.4.5.RELEASE</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.6.Final</version>
</dependency>
</dependencies>
</project>
CassandraConfig.java
#Configuration
#EnableCassandraRepositories(basePackages = { "org.spring.cassandra.example.repo" })
public class CassandraConfig {
private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
#Value("${cassandra.hostnames}")
private String hostnames ;
#Value("${cassandra.username}")
private String username ;
#Value("${cassandra.password}")
private String password ;
#Value("${cassandra.keyspace}")
private String keyspace ;
#Value("${cassandra.isSsl}")
private boolean isSsl ;
#Value("${cassandra.port}")
private int port;
#Bean
Public CassandraClusterFactoryBean cluster() {
CassandraClusterFactoryBean cluster = new CassandraClusterFactoryBean();
PlainTextAuthProvider authProvider = new PlainTextAuthProvider(username, password);
cluster.setContactPoints(hostnames);
cluster.setPort(port);
cluster.setUsername(username);
cluster.setPassword(password);
return cluster;
}
#Bean
Public CassandraMappingContext mappingContext() {
return new BasicCassandraMappingContext();
}
#Bean
Public CassandraConverter converter() {
return new MappingCassandraConverter(mappingContext());
}
#Bean
Public CassandraSessionFactoryBean session() throws Exception {
CassandraSessionFactoryBean session = new CassandraSessionFactoryBean();
session.setCluster(cluster().getObject());
session.setKeyspaceName(keyspace);
session.setConverter(converter());
session.setSchemaAction(SchemaAction.NONE);
return session;
}
#Bean
Public CassandraOperations cassandraTemplate() throws Exception {
return new CassandraTemplate(session().getObject());
}
}
Please let me know if I am doing anything wrong here.

Neo4j spring data Data polution

{
"id": 109433,
"name": "test",
"value": [
"c"
]
}
Having the node above I execute this post to modify my object so the value contains "a","b" instead of "c":
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d ' {
"id": 109433,
"name": "test",
"value": [
"a","b"
]
}' 'http://localhost:8080/configs'
Then I execute a get to get all nodes
curl -X GET --header 'Accept: application/json' 'http://localhost:8080/configs'
For some weird reason it will return
{
"id": 109433,
"name": "test",
"value": [
"a",
"b",
"c"
]
}
If I go to neo4j outside my web application and query it I will get
{
"id": 109433,
"name": "test",
"value": [
"a","b"
]
}
So just to be sure I have some sort of data pollution like a cache running somewhere I stop the server and turn it on again, then I do the get again
curl -X GET --header 'Accept: application/json' 'http://localhost:8080/configs'
returns:
{
"id": 109433,
"name": "test",
"value": [
"a",
"b",
]
}
So now "c" is nowhere to be seen.
Here is the code I'm using
api
package io.swagger.api;
import io.swagger.annotations.*;
import io.swagger.model.Config;
import io.swagger.service.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
#RestController
#RequestMapping(value = "/configs", produces = {APPLICATION_JSON_VALUE})
#Api(value = "/configs", description = "the configs API")
public class ConfigsApi {
#Autowired
private ConfigService configService;
#ApiOperation(value = "", notes = "Gets `Config` objects. ", response = Config.class, responseContainer = "List")
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Successful response", response = Config.class) })
#RequestMapping(value = "", produces = { "application/json" }, method = RequestMethod.GET)
public ResponseEntity<List<Config>> getAllConfigs() throws NotFoundException {
return new ResponseEntity<List<Config>>(configService.getAll(),HttpStatus.OK);
}
#ApiOperation(value = "", notes = "Creates/updates `Config` object. ", response = Void.class)
#ApiResponses(value = {
#ApiResponse(code = 200, message = "successful operation", response = Void.class),
#ApiResponse(code = 400, message = "Invalid Config", response = Void.class) })
#RequestMapping(value = "", produces = { "application/json" }, method = RequestMethod.POST)
public ResponseEntity<Void> createConfigByKey( #ApiParam(value = "Updated user object" ,required=true ) #RequestBody Config body ) throws NotFoundException {
configService.merge(body);
return new ResponseEntity<Void>(HttpStatus.OK);
}
}
Service
package io.swagger.service;
import com.google.common.collect.Lists;
import io.swagger.model.Config;
import io.swagger.repository.ConfigRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
#Slf4j
#Service
public class ConfigService {
#Autowired
private ConfigRepository configRepository;
public List<Config> getAll() {return Lists.newArrayList(configRepository.findAll());}
public void merge(Config c){configRepository.save(c);}
}
Repository
package io.swagger.repository;
import io.swagger.model.Config;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.GraphRepository;
public interface ConfigRepository extends GraphRepository<Config> {
}
Neo4j Configuration
package io.swagger.configuration;
import org.neo4j.ogm.session.SessionFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.config.Neo4jConfiguration;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
#Configuration
#EnableNeo4jRepositories("io.swagger.*")
public class InventoryApiNeo4jConfiguration extends Neo4jConfiguration {
#Value("${neo4j.ogm.driver}")
private String driver;
#Value("${neo4j.ogm.URI}")
private String uri;
#Value("${neo4j.ogm.connection.pool.size}")
private int connectionPoolSize;
#Value("${neo4j.ogm.encryption.level}")
private String encryptionLevel;
#Bean
public org.neo4j.ogm.config.Configuration getConfiguration() {
org.neo4j.ogm.config.Configuration configuration = new org.neo4j.ogm.config.Configuration();
configuration.driverConfiguration()
.setDriverClassName(driver)
.setURI(uri)
.setConnectionPoolSize(connectionPoolSize)
.setEncryptionLevel(encryptionLevel);
return configuration;
}
#Override
#Bean
public SessionFactory getSessionFactory() {
return new SessionFactory(getConfiguration(), "io.swagger");
}
}
Pom
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.swagger</groupId>
<artifactId>swagger-springboot-server</artifactId>
<packaging>jar</packaging>
<name>swagger-springboot-server</name>
<version>1.0.0</version>
<properties>
<springfox-version>2.4.0</springfox-version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RC1</version>
</parent>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--SpringFox dependencies -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox-version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox-version}</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
<scope>provided</scope>
</dependency>
<!-- Neo4J -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j</artifactId>
<version>4.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-bolt-driver</artifactId>
<version>2.0.3</version>
</dependency>
</dependencies><repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
Updated Spring boot from 1.4.0.RC1 to 1.4.0.RELEASE and now it does not occur.

Spring Boot and Spring Security not honoring configureGlobal

I created a simple SpringBoot app and added spring security. When I login it is only accepting the default password it is generating.
It won't let me login using the username/password I have configured in WebSecurityConfigurerAdapter.
Here is my code. SsFirstApplication.java
#SpringBootApplication
#EnableAutoConfiguration
public class SsFirstApplication {
public static void main(String[] args) {
SpringApplication.run(SsFirstApplication.class, args);
}
}
My custom security config "SecurityConfig.java"
#Configuration
#EnableWebSecurity
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Autowired
public void configureGlobal(AuthenticationManagerBuilder authBuilder) throws Exception{
logInfo("configureGlobal");
authBuilder
.inMemoryAuthentication()
.withUser("user")
.password("password123");
//.roles("USER");
}
private void logInfo(String strToken){
for(int index=0;index<1;index++){
System.out.println("************************** "+strToken+" ****************************");
}
}
#Override
protected void configure(HttpSecurity http) throws Exception{
logInfo("configure");
http
.authorizeRequests()
.anyRequest().authenticated();
}
}
And finally the Web App Initializer "SecurityWebApplicationInitializer"
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer{
public SecurityWebApplicationInitializer(){
super(SecurityConfig.class);
}
protected Class<?>[] getRootConfigClasses() {
return new Class[] { SecurityConfig.class };
}
}
When I start the SpringBoot app (I am using STS/Eclipse IDE) in the console it is generating and printing out the password for username "user".
When I try http://localhost:8080/admin it won't let me use the username/password I configured.
Here is my pom.xml
<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.test</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>ss-first</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<start-class>demo.SsFirstApplication</start-class>
<java.version>1.8</java.version>
</properties>
<dependencies>
<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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-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>
The configuration of Spring MVC and Spring security needs to be corrected. Following will be the configuration for you.
#SpringBootApplication
#Controller
public class App extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
#RequestMapping(value="/")
public String home() {
return "admin";
}
The SecurityConfig is more or less correct except you need to add the login url information as shown below.
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().fullyAuthenticated().and().formLogin()
.loginPage("/login").failureUrl("/login?error").permitAll();
http.csrf().disable();
}
As menionted in the comments above SecurityWebApplicationInitializer is also not needed in your config.

Resources