What is right place for placing Jersey ResourceConfig - jersey

I have following projects :
web,
Rest,
Service
Can anyone please tell me, what is the best place to keep code for class which extends Jersey's org.glassfish.jersey.server.ResourceConfig.Wether class. It should be in Web project or Rest project ?

In my projects i keep the ResourceConfig class close to the ResourceClasses (the actual restclasses). Which should be the Rest Project in your case
I do this for the following reasons
The ResourceConfig controls how your Resources gets loaded so i makes sense to have them near the resourceclasses
It gives you the ability to use your ResourceConfig in your (Unit|Integration)Tests, maybe even use 2 different Configs that extend a DefaultConfig for things like Fakedatabases vs real databases in Test and Production but the general configuration like RestImpl binds to RestInterface (where the actual annotations are) resides in the DefaultConfig
I hope it's clear what i want to say.

Related

ClassCastException in multi-module project running on Quarkus (gradle)

I seem the get weird classcast exceptions in multi-module project.
Here is an shortened overview of the project structure:
Project: dto-commons
contains
-> AuditingEntityObjectSelector (a normal java class)
-> AbstractAuditingEntity (JPA #MappedSuperClass)
Project: model
contains lots of JPA entities, which all extend AbstractAuditingEntity from the project 'dto-commons'
depends on
-> dto-commons
Project: selectors
contains
-> SampleRequestSelector (a normal java class which extends AuditingEntityObjectSelector from the project 'dto-commons'
depends on
-> model
Project:mainservices
- model
- selectors
- dto-commons
Project:rest-api --> This project is launched with quarkusDev (gradle)
- mainservices
I've created a little testresource where I inject some services, an EntityManager etc.
Everything seems to be working, except that I get very weird ClassCastExceptions
java.lang.ClassCastException: class
com.geodesk.queryinfrastructure.selector.SampleRequestSelector cannot
be cast to class
com.geodesk.domain.queryinfrastructure.AuditingEntityObjectSelector
Some debugging shows me the following:
new SampleRequest() instanceof AbstractAuditingEntity --> true (which is correct)
new SampleRequestSelector() instanceof AuditingEntityObjectSelector --> false (which is NOT correct)
This is probably a classloading issue, but I can't figure out what is causing this.
SampleRequest.class.classLoader == AbstractAuditingEntity.class.classloader --> true
SampleRequestSelector.class.classLoader == AuditingEntityObjectSelector.class.classloader --> false (don't know for sure, but I think that should be true)
Anyone can point me in the right direction?
(note that all projects do have an empty META-INF/beans.xml in their resources dir)
This looks like another installment of our class loader issues. We are currently actively working on fixing them but it's not an easy subject.
I suppose you only have the issue with quarkusDev? Not when you execute the -runner.jar?
It would be helpful if you could try to put together a simple reproducer and open a GH issue so that we can be sure the current class loader work fixes this issue too.

Executing extension before SpringExtension

I'm trying to implement integration testing in my app and have test class like that:
#ExtendWith(value={MyDockerExtension.class})
#ExtendWith(value={SpringExtension.class})
#WebAppConfiguration
#ContextConfiguration(classes={...})
#TestInstance(TestInstance.LifeCycle.PER_CLASS)
public class TestClass{ ... }
Is there any way to make MyDockerExtension execute some code, before whole SpringExtension start working and generate whole Context with Configurationc classes?
I've heard that order in which we declare extensions is the key, but sadly MyDockerExtension that implements BeforeAllCallback, AfterAllCallback executes right before test method and after whole context is loaded. In that situation it's to late to start containers with docker, becuase since whole context is loaded my app already tried to connect to the container.
At first I was skeptical about the order being fixed but you're correct:
Extensions registered declaratively via #ExtendWith will be executed in the order in which they are declared in the source code.
Regarding the MyDockerExtension, you may want to look at the extension point TestInstancePostProcessor, which is called before #BeforeAll. SpringExtension implements it and I guess it's there where it sets up the application context. If you also implement it, you should be able to act before it does.

Can't find #SpringBootApplication from JUnit test file

I was following the guide here, https://spring.io/guides/gs/spring-boot/ - cloned the project, built with Gradle and tried to run...application ran fine. Then I changed some file structure as per my requirement and tried to run the unit test case given there, but getting this error -
Unable to find a #SpringBootConfiguration, you need to use #ContextConfiguration or #SpringBootTest(classes=...) with your test
I only restructure the codes in there, and this is my current project structure -
/projectroot
- /src/main/java
-Application.java
-/controller
-MyController.java
-/util
-MyUtil.java
-/model
-MyModel.java
Now trying to run test case from
/src/test/java/controller/MyControllerTest.java
I have gone through this Stack Overflow link and understood that if I put my test folder under /src/main/java/ it may work. But if I do that test file doesn't compile and it also doesn't seem the right way to put application code along with test code. I know I'm missing something very fundamental.
The way you setup your test (using the whole spring boot context), I believe MyControllerTest.java needs to be at most at the same level as Application.java. Also, I notice Application.java is using default package, you should move it into a package, so that all your beans are below your Spring Boot main class:
/projectroot
- /src/main/java/com/example/project/
-Application.java
-/controller
-MyController.java
-/util
-MyUtil.java
-/model
-MyModel.java
- /src/test/java/com/example/project/
-MyControllerTest.java
Spring's documentation
How Spring Boot's context is resolved from a test:
The search algorithm works up from the package that contains the test
until it finds a #SpringBootApplication or #SpringBootConfiguration
annotated class. As long as you’ve structure your code in a sensible
way your main configuration is usually found.
About using the default package with Spring Boot:
When a class doesn’t include a package declaration it is considered to
be in the “default package”. The use of the “default package” is
generally discouraged, and should be avoided. It can cause particular
problems for Spring Boot applications that use #ComponentScan,
#EntityScan or #SpringBootApplication annotations, since every class
from every jar, will be read.
We recommend that you follow Java’s recommended package naming conventions and use a reversed domain name (for example, com.example.project).

Making services in Tapestry 5: No service implements the interface

I'm developing my first Tapestry application with a login system based on a Hibernate database.
On one page with a session object, I want to call my Authenticator service class, which also gets the session injected and does some stuff. My problem is, I can't get any services to run, it's been very frustrating, despite me following simple guides like this one: http://code.google.com/p/shams/wiki/Service
In my services package, I got the Authenticator.java and AuthenticatorImpl.java interface and implemented class. In the AppModule class, I call
binder.bind(Authenticator.class, AuthenticatorImpl.class);
And in my page 'ShowAllUsers' I inject my Authenticator service object:
...
public class ShowAllUsers{
#Inject
private Session session;
#Inject
private Authenticator authenticator;
...
}
But when I load the page on my server, I receive following error:
org.apache.tapestry5.ioc.internal.OperationException
Error obtaining injected value for field de.webtech2.pages.user.ShowAllUsers.authenticator: No service implements the interface de.webtech2.services.Authenticator.
trace:
- Creating instantiator for component class de.webtech2.pages.user.ShowAllUsers
- Running component class transformations on de.webtech2.pages.user.ShowAllUsers
- Injecting field de.webtech2.pages.user.ShowAllUsers.authenticator
But my AppModule does bind the class to the interface successfully. In the Maven build console I can read "Authenticator: DEFINED" and if I try to bind it in another module, it complains because it's bound in AppMopule already.
Why doesn't tapestry see the implementation? What am I doing wrong?
Glad you checked the startup log output, that's certainly the first "sanity check" towards addressing this problem.
I think uklance has the right idea: do a clean build, make sure you don't have multiple classes named Authenticator floating around ... perhaps from a 3rd party library. I'm always having problems where I accidentally import a non-Tapestry class that happens to be named "Resource" or something.
I haven't solved the issue itself but I found a workaround that fixes it. As you might find on the internet, Tapestry allows for auto-reloading classes. Pages and components do work fine, services have some limitations -- this is where there seem to arise issues. Tomcat doesn't link the interface to the implementation.
Fix: A simple restart of eclipse solves this. Meh.
(This also fixes the "method not found" error if you added a new method to an existing service)
Also, when I execute mvn clean, everything gets screwed many times over. Eclipse can no longer resolve the simplest class and package references. Classes in the same package can no longer be found, or references to the javax.internet package lead into eternal nothingness -- whereas everything was working just fine a moment ago.
Fix:
Right-click eclipse project -> Properties -> Maven
Tick the checkbox for "Resolve dependencies from Workspace projects" and hit Apply.
If it is already checked, uncheck -> apply, then recheck -> apply. Eclipse should go sane again -- until next time...

maven: Running the same tests for different configurations

In my spring + maven app, I have created some tests for the Data Access Layer that I would like now to run against multiple datasources. I have something like:
#ContextConfiguration(locations={"file:src/test/resources/testAppConfigMysql.xml"})
public class TestFooDao extends AbstractTransactionalJUnit38SpringContextTests {
public void testFoo(){
...
}
}
It has currently the config location hardcoded, so it can be used only against one datasource.
What is the best way to invoke the test twice and pass two different configs (say testAppConfigMysql.xml and testMyConfigHsqlDb.xml)?
I've seen suggestions to do this via system properties. How can I tell maven to invoke the tests twice, with different values of a system property?
I don't know if there is some sexy and fancy solution, being simple as well, for this. I would just implement base class with all testing stuff and then inherit it into 2 classes with different annotation-based configuration, like this:
#ContextConfiguration(locations={"firstDs.xml"})
public class TestFooDaoUsingFirstDs extends TestFooDao {
}
#ContextConfiguration(locations={"secondDs.xml"})
public class TestFooDaoUsingSecondDs extends TestFooDao {
}
Unless you have to handle really high number of different datasources this way, that is OK for me.
Rather than file:..., you can use classpath:... (remove the src/test/resources, it's implicit if you use classpath). Then you can have a single master context with the line:
<import resource="dao-${datasource}.xml" />
If you run the Maven build with the option -Ddatasource=foo, it will replace the ${datasource} in the master context with the whatever you specify. So you can have datasource-foo.xml, datasource-bar.xml etc. for your different configurations.
(You need to enable Maven resource filtering in the POM for this to work).
Alternatively, check out the new stuff in Spring 3.1: http://www.baeldung.com/2012/03/12/project-configuration-with-spring/
Edit: A third option would be to have all the test classes extend some superclass, and use
Junit's #Parameterised, where the parameters are the different Spring contexts. You couldn't use #ContextConfiguration in that case, but you can always create the Spring context manually, then autowire the test class using org.springframework.beans.factory.config.AutowireCapableBeanFactory.autowireBean()
Check maven invoker plugin. It supports profiles also.

Resources