How to use #Service class from another Web App Project - java

I'm having a problem right now, I have two Dynamic Web App Project (ProjectA and ProjectB) and I need to reuse methods from Service class from ProjectA. Right now I'm developing ProjectB, the methods I need to reuse from ProjectA are pulling datas from its own database, and I need to have those data.
I've already done doing this following steps
Java Build Path -> Add Project
Project Reference -> Add Project
and I also tried to add ProjectA jar file as Maven dependency and still not working
In ProjectB, I can already import and call methods from ProjectA but I'm having a nullPointerException.
ProjectA.java
public interface CustomerService {
public Customer getCustomerDetails(Long id);
}
The above class is the class that I need to reuse, for to me have ProjectA data.
ProjectB.java
public class CustomerController {
private CustomerService customerService;//service from another project
public ModelAndView getCustomer(Long id){
Customer = this.customerService.getCustomerDetails(id);
}
}
Now, In ProjectB I need to call CustomerService.class and use its own method for me to have its own data. But unluckily I'm having a NullPointerException everytime call CustomerService interface
Please help I can't get the right thing to do.
Thanks in advance

Your problem is that you are not telling Spring to instantiate an object that implements CustomerService, for being injected in CustomerController. You can do:
Annotate the CustomerService implementation (CustomerServiceImpl in ProjectA??) with #Service, for tell Spring to instantiate that implementation.
Add jar of ProjectA in ProjectB
Tell Spring to scan for beans to instantiate, in xml configuration file: <context:component-scan base-package="base.package.in.project.a" />
Annotate customerService property in CustomerController with #Autowired for inject the instance of CustomerServiceImpl in spring context into this property.

Related

unable to autowire custom spring boot library project to my application

Importing custom spring-boot library jar to my application, and autowiring show the following error when I run the application
Parameter 0 of constructor in com.dilla.de.orca.addresssvc.service.TestScheduler required a bean of type 'com.dilla.de.orca.flowersvc.service.FlowerServiceImpl' that could not be found.
The Library module has following packages
Configuration
FlowerServiceConfiguration - create beans for Jaxb2Marshaller, WebServiceTemplate,
webserviceMessageSender
Model
Service
FlowerService (an interface no annotation)
FlowerServiceImp implements the interface and calls FlowerAdapter
FlowerAdapter (call external webservice)
Src/main/resources
Application.properties define external webservice url, and related properties
FlowerSvcLibApplication.java
public static void main(final String[] args) {
SpringApplication.run(FlowerSvcLibApplication.class, args);
}
I was autowiring the Flower Service interface as follows, in my application to test functionality
of library jar
#Component
public class MyFlowerService {
private FlowerService service;
#Autowired
public MyFlowerService(final FlowerService service) {
this.service = service;
}
I got the error I posted earlier. I did do more research, and one suggestion was creating “own auto-configuration”, but I still did not understand. How do I create autoConfiguration class to handle to autowire my library class, and also how does client using my library provide application property values. Currently, I hard coded actual values for example a webservice url, and now client can change this to be test or prod, and to do that how does my library module setup should be?
Please check #ComponenetScan & make sure that it has package path something like this “com.dilla.de.orca”

Cannot find the Repository bean in Spring boot / Spring Data MongoDB

I have created a spring project which has a controller and all of its logic is written in Service Interface, which is implemented by ServiceImpl class. I have a repository with which has a model.
//Service Interface
public interface Service{
List<Model> getAllKpiData();
}
//ServiceImpl Class
#Service
public class ServiceImpl implements Service{
#Autowired
private KPIRepository kpiRepository;
#override
private List<Model> getAllKpiData()
{
this.kpiRepository.findAll();
//gets me an empty list.
}
}
//KPIRepository
#Repository
public inerface KPIRepository extends MongoRepository<KPIModel, String>
{
}
//Another Service Interface in another package
public interface AnotherService{
List<Model> getAllKpiData();
}
//ServiceImpl Class
#Service
public class AnotherServiceImpl implements Service{
#Autowired
private KPIRepository kpiRepository;
#override
private List<Model> getAllKpiData()
{
this.kpiRepository.findAll();
//gets me list of values, which are inside the repo(master data).
}
}
Both of them are pointing to same repo, but in AnotherService class i am able to get values inside the repository, whereas i am not able to get any values inside Service, on doing this.kpiRepository.findAll().
Do you have spring-boot-starter-data-mongodb dependency on classpath? If yes, then is KPIRepository in the same package as your main class? If not then in your main class put this annotation #EnableMongoRepositories(basePackageClasses=KPIRepository.class) to safely tell Spring Data MongoDB to scan a different root package by type if your project layout has multiple projects and its not finding your repositories. Or you can use #EnableMongoRepositories(basePackages = "com.acme.repositories.mongo") to specify the package that contains all of your repositories.
The presense of spring-boot-starter-data-mongodb will automatically enable #EnableMongoRepositories. And Spring will automatically create proxies of all classes implementing Repository<T,ID> (your class implements MongoRepository, which itself implements Repository) and create beans of them and make them available for injection. And when your repository is in a different package then it is unable to create proxies of your repository, hence fails to create a bean of it. And since there is no bean, it cannot inject it, hence you see the error.
Did you use the #EnableMongoRepositories annotation? Take a look to this link: https://docs.spring.io/spring-data/mongodb/docs/1.2.0.RELEASE/reference/html/mongo.repositories.html. Review the "6.2 usage" point.
Regards

Java SpringMVC where to place the RepositoryRestMvcConfiguration (#Configuration) file

I have come across so many tutorials about configuration files for java SpringMVC projects and usually have the #Configuration at their class name but they never mention where exactly to place these files.
For example I have learnt that I might be able to change Spring Data Rest rest api by extending the RepositoryRestMvcConfiguration.
1) I want to be able to be able to have longer urls for the repositories so instead of having api/amazonproducts I could have api/amazon/products. Apparently this is impossible. I end up having;
#RepositoryRestResource(collectionResourceRel = "amazonproducts", path = "amazonproducts")
#CrossOrigin
public interface AmazonProductRepository extends PagingAndSortingRepository<AmazonProduct, Long> {
https://docs.spring.io/spring-data/rest/docs/current/api/org/springframework/data/rest/webmvc/config/RepositoryRestMvcConfiguration.html
All I have to do is for example create class like;
class CustomRestMvcConfiguration extends RepositoryRestMvcConfiguration {
#Override
#Bean
public HateoasPageableHandlerMethodArgumentResolver pageableResolver() {
HateoasPageableHandlerMethodArgumentResolver resolver = super.pageableResolver();
resolver.setOneIndexedParameters(true);
return resolver;
}
}
I don't know in which file/folder to place this code. I am using Eclipse Java EE Oxygen. I have created a maven project and I am currently testing it on spring-boot
You can place #Configuration annotated classes in any package you want, as long as the package is included in the component scanning.
In Spring Boot, that by default means in the same package as the class with #SpringBootApplication, or any subpackage thereof, same as for all other classes managed by Spring.
Other than that, Spring doesn't care about package names.

Cucumber CDI injection does not work with beans in src/main/java

I have a JEE application in a maven project using JUnit and Cucumber to test my code. The application is using CDI with weld-se in test scope.
I have created a simple feature file src/test/resources/specification/first.feature
Scenario: Identified user
Given I am user A
Then I created the corresponding cucumber step:
public class FirstSteps {
#Inject
UserService userService;
#Given("^I am user A$")
public void i_am_user_A() throws Throwable {
User user = User.new().withName("user A").create();
assertThat(userService.getActualUser()).isEqualTo(user);
}
}
User Service is an Interface with one trivial implementation:
public interface UserService {
User getActualUser();
}
public class FakeUserService implements UserService {
#Override
public User getActualUser() {
return User.new().withName("user A").create();
}
}
There are empty beans.xml files in src/main/resources/META-INF and src/test/resources/META-INF.
The step is located in src/test/resources, the service interface and its implementation in src/main/java.
And here is the JUnit-Test for it:
#RunWith(Cucumber.class)
#CucumberOptions(
features = {"classpath:specifikation"},
glue = {"mypackage"})
public final class CucumberTests {
}
The step is found by cucumber and gets executed. But CDI does not work:
Exception in thread "main" org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type UserService with qualifiers #Default
at injection point [BackedAnnotatedField] #Inject mypackage.FirstSteps.userService
I have found this issue on github for cucumber. But the solution does not work for me. I already have two empty beans.xml files in src/main/resources/META-INF and src/test/resources/META-INF.
It seems like the weld container creates a context for src/test only and everything in src/main does not belong to it. When I move the service interface and implementation to src/test/java it works...
Is there a way to reference beans in src/main from src/test?
EDIT: corrected location of the service interface
Assuming that your step is located in src/test/java and your service (interface) is located in src/main/java and not in src/(test|main)/resources (typo?), your setup should work.
Maybe check the following:
Ensure that your src/main/java and src/test/java folders are on the same classpath.
Assuming that you are using a current version of Weld which is CDI >1.1 compliant, ensure that both folders are explicit bean archives.
Ensure your beans.xml files are literally empty or have bean-discovery-mode set to all.
If that does not work either, try to annotate your FakeUserService.

No matching bean of type found for dependency: Spring MVC

I am getting this error when trying to use #autowire, #configuration, #bean, #Repository in my Spring MVC project
Could not autowire field: private com.sachin.dao.StockDaoImpl com.sachin.myapp.HomeController.stockDao;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.sachin.dao.StockDaoImpl] found for dependency:
Please let me know what mistake I am making. I am new to Spring MVC and dependency injection.
Here is my controller code. I am trying to inject StockDaoImpl in the controller.
#Controller
public class HomeController {
#Autowired
private StockDaoImpl stockDao;
#RequestMapping(value = "/stockgoogle/", method = RequestMethod.GET)
public #ResponseBody Stock stockGoogle(Locale locale, Model model) {
//StockDaoImpl stockDao = new StockDaoImpl();
Stock s=stockDao.listGoogle();
model.addAttribute("s", s );
return s;
}
}
My Service Implementation is below. I have used #Repository annotation here with "stockDao" which is my variable name in controller that I want to inject
#Repository("stockDao")
public class StockDaoImpl implements StockDao {
#Override
public Stock listGoogle() {
Stock s = null;
try {
... //some code
String name = rs.getString("Name");
s = new Stock(name);
...
} catch (Exception e) {
}
return s;
}
}
Also I have created a configuration class separately. I am using this to define my bean. I am only using this to specify bean and have not imported it anywhere in the code.
#Configuration
public class BeanConfiguration {
#Bean
public StockDaoImpl stockDao(){
return new StockDaoImpl();
}
}
Am I missing something here. From looking at the error it looks like the #Bean annotation is not visible to the factory. Do I have to do anything else other than annotating the #configuration class.
I might also be using the annotations in a wrong way. I could be making a mistake in how I am using #Autowired or #Repository.
Can you please help.
I think this might be your issue:
"Also I have created a configuration class separately. I am using this to define my bean. I am only using this to specify bean and have not imported it anywhere in the code."
Somewhere you need to tell Spring to look for BeanConfiguration. You can do this in your applicationContext.xml file (assuming you have one) as follows:
<context:component-scan base-package="com.sachin.config" />
This assumes BeanConfiguration is in the com.sachin.config package.
If you can't find where to put this it may be helpful to share your web.xml file.
I am having the described behaviour in a test class.
I work in IntelliJ 2020.1, with an old project build on:
Java 1.6
Spring 3.0.5.RELEASE
Maven POM 4.0.0
Maven 3.2.5
The test class starts as:
#Test
#ContextConfiguration(locations={ "classpath*:beans_sets/UhradyForIns.xml"})
#TransactionConfiguration(transactionManager="transactionManager", defaultRollback=false)
#DirtiesContext(classMode= DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class OdeslatJakobyAutomatickyUhraduTest extends TestBaseWithProperties {
private static final Logger log = LoggerFactory.getLogger(OdeslatJakobyAutomatickyUhraduTest.class);
#Autowired
U01UhradaBaseJpaDaoForTesting dao;
Sometimes suddenly, after some changes in POMs, Spring cannot autowire the dao giving exactly your messages. The dao is well described by its class and by XML context description but is suddenly invisible for Spring. I have tried many ways described on SO, adding annotations, changing configuration, but I have found, that it is all excessive. All I need is only to refresh the maven repositories 4 times by 4 different orders subsequently:
1. mvn -e -U clean install //In cmd line
2. Ctrl+Shift+A Reimport maven //in IntelliJ
3. double round arrows for refresh //in the maven window of IntelliJ
4. AGAIN REPEAT THE FIRST REFRESH.
After that, it is all OK and works fine till the next greater change in POMs.
Or... Till due to some inner reasons, Maven or IntelliJ damages the local jar repository without your participation. At least, I had a case, when I haven't touched the repository, but again that Could not autowire... message appeared. But this time only one
mvn -e -U clean install
was enough.
Obviously, there is/are some error(s) in the maven and/or maven plugin in IntelliJ. That problem is shown by Could not autowire... message. The repair is possible by a simple maven repository refresh or, in worse cases, demand a sequence of several different repository refreshes.
I understand that it has no obvious logic in that solution, and our developer's work resembles magic more and more. And this time, definitely, it is not your or my vice. Simply we have to adapt to existing errors. At least we know how to do it.

Categories

Resources