Why does the package matter for Spring RESTful controller classes - spring

I have the Spring sample RESTful server running. If I add controller classes to the com.example.restservice package, they work. But if I put the same class in the package net.windward.RESTfulEngine.Controllers - they are not found.
I don't see any setting anywhere. What is limiting where these controllers need to be located?

Spring starts scanning the packages from the main package that your #SpringBootApplication class exists and all of its sub-packages.for your case you need to use #ComponentScan in order to scan external packages.

It could work if you would define both package patterns to scan for an example
<context:component-scan base-package="com.example, net.windward" />
Or in Java code would be like
#ComponentScan({"com.example","net.windward"})
But if you would want to have only one package pattern scanned, then you need to keep them in order for an example to start everything with com. and add rest of your packages.
What component scan does it starts from "com." or whatever you defined in your configuration and it goes into all subdirectories, but only subdirectories, it does not scan around it. So if you would like to scan com. and net. you need to define both of them so spring can go into both of their subdirectories.
But approaches would do the work.

Related

Exclude some components of a Microservice

I am a new bee and using microservices(Spring Boot, Spring Cloud) in which I am trying to use resource file of a microservice in another. For that I need to scan that module in another one via ComponentScan.
Like I have an Admin module in which I need to autowired Main Resource that is in main module.So I use:
#ComponentScan(basePackages = {"com.example.admin","com.example.main"}
I used this in AdminApplication file.Now it also shows Main module's Controllers in Admin which I don't want. I google it and apply:
#ComponentScan(basePackages =
{"com.example.admin","com.example.main"},
excludeFilters = {#ComponentScan.Filter(type = ASSIGNABLE_TYPE,
value = {
UserController.class,
CustomerController.class,
SchoolController.class
})})
But it still shows this Main module controllers in Admin Module. How to actually exclude this? Please help me.
With JavaConfig (#Configuration) and the #Profile annotation, you could set up a subtile combination of classes "in and out" depending of your needs, I guess.
BUT you would have to disable #ComponentScan on your main class (don't use #SpringBootApplication, maybe, as it's embedding #ComponentScan).
IMHO you should rather modularize your applications/services, building common resources as a separated JAR, and each service as a distinct Maven module depending on it
Thanks for your suggestions. Finally I got the answer.
Swashbuckle is built on top of WebApi's built-in metadata layer - ApiExplorer. If you decorate a controller or action with the following attribute:
[ApiExplorerSettings(IgnoreApi=true)]
public class MyController : ApiController
then this will ultimately cause the entire controller or individual action to be omitted from the Swagger output .

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).

Deploying BEAN in OSGi plugin

I am currently deploying my custom controls as OSGi plugins and I wanted to do the same thing with my beans. I have tried putting them into the OSGi plugin and it works fine but the only problem I have is the faces-config.
It seems it has to be called faces-config in the OSGi plugin to work but that means i can't use beans in the NSF anymore because it seems to ignore the local faces-config.
Is there a way to change the name of the faces-config in the OSGi plugin?
Something like FEATURE-faces-config.xml?
In the class in your plugin that extends AbstractXspLibrary, you can override "getFacesConfigFiles", which should return an array of strings representing paths within the plugin to additional files of any name to load as faces-config additions. For example:
#Override
public String[] getFacesConfigFiles() {
return new String[] {
"com/example/config/beans.xml"
};
}
Then you can put the config file in that path within your Java source folder (or another folder that is included in build.properties) and it will be loaded in addition to your app's normal faces-config, beans and all.
The NSFs are running as separate, distinct Java applications. The OSGi plugin is running in the OSGi layer, above all those distinct Java applications, as a single code base. Consequently, the faces-config is only at that level.
It's possible to load them dynamically, by using an ImplicitObjectFactory, loaded from an XspContributor. That's what is done in OpenNTF Domino API for e.g. userScope (which is a bean stored in applicationScope of an NSF). See org.openntf.domino.xsp.helpers.OpenntfDominoImplicitObjectFactory, which is referenced in OpenntfDominoXspContributor, loaded via the extension point of type "com.ibm.xsp.library.Contributor".
A few caveats:
You have no control over what happens if you try to register your bean with a name the developer also uses for a different variable in that scope.
Unless you add code to check if the library is enabled, as we do, you'll be adding the bean to every database on the server.
You still need to add the library to the NSF. Unless you also provide a component that those databases will all use, there's no way you can programmatically add it, as far as I know.
It might be easier to skip the bean approach and just add an instance of the Java class in beforePageLoad, page controller class, or however you're managing the backing to the relevant XPage (if viewScope) or application (if sessionScope / applicationScope).

Generating CRUD with Appfuse Maven Plugin(AMP)

A few Days Ago I Used the Command mvn appfuse:gen to generate CRUD with the Appfuse. But it Generated the folllowing files/classes for a given class (say, Category):
1) Category-validation.xml
2) CategoryAction-validation.xml
3) CategoryAction.java
4) CategoryActionTest.java
5) CategoryForm.jsp
6) CategoryList.jsp
I Expected it will generate the CategoryDao/CategoryDaoHibernate or maybe CategoryManager/CategoryManagerImpl Classes at least !!! But I was wrong.
Instead, we have the following code in CategoryAction class:
private GenericManager categoryManager;
And this is in Contradiction with the appfuse's standard tutorial (See this Page)
Can anybody tells me how to generate the CategoryDao/CategoryDaoHibernate and CategoryManager/CategoryManagerImpl Classes for the project?
Use -Damp.genericCore=false when you run appfuse:gen. Like the following:
mvn appfuse:gen -Dentity=Category -Damp.genericCore=false
It's already explained in following post:
Stackoverflow: running “mvn appfuse:gen” does nothing
but basically, it's the same like previous post from Matt Raible
After running that command (for EVERY entity), you'll get:
DAO layer
DAO interfaces
DAO (Hibernate) implementation
Service layer
Manager interfaces
Manager implementations
Webapp layer
Controllers (if you are using SpringMVC framework)
JSP pages
and whole bunch of all other required resources (various Resource Bundle properties, Spring XML files, Menu configurations...). Of course, it's all based on your model, your defined JavaBean classes.
After that, you just need to put some extra code inside implementation classes if you need some customized functionalities, some additional business logic.
I hope it helps.

How can I package an extensible default Spring configuration in my framework?

It is the second time that I stumble across that issue and I haven't found a good solution yet. My problem is that I want to package a framework like JAR with a default Spring context and give the user of my JAR package the possibility to use this configuration (or even an ApplicationContext implementation) to add his own bean definitions (from another config file) and to use or overwrite definitions from the default context. Does anybody know a good way to do this?
The people using your jar will have to import your .xml file in theirs, with something like this:
<import resource="classpath*:/META-INF/spring-yourframework-init.xml" />
(/META-INF/spring-yourframework-init.xml is the path of your xml in your jar. This xml file is a regular spring configuration file)

Resources