It seems to be a simple question but yet i couldn't find clear answer while searching documentation and forums. I'm migrating from xml to java-based config (Spring 5.1.9). Due to some legacy restrictions in xml config i need to create a bean from some side library's non public class:
SampleClass.class
package side.library
class SampleClass {
//... some code here
}
context.xml
...
<bean id = "sampleId" class "side.library.SampleClass">
...
And this works fine since Spring uses reflection inside and it creates bean without any problems at compile/runtime, but in java-based config usage of such class leads to an access error:
package my.configuration;
import side.library.SampleClass; // 'side.library.SampleClass' is not public in 'side.library'. Cannot be accessed from outside package
#Configuration
public class JavaConfiguration{
#Bean
public SampleClass sampleClass() {
return new SampleClass(); // same error text
}
}
So, what is the proper way to deal with this sutiation? Using reflection libs in #Configuration class to reach this class seems to be a bad idea.
just a workaround: create a wrapper class in the outer project in the same package and use this class in your configuration.
package com.legacy;
public class Wrapper {
private LegacyImpl legacyImpl;
public Wrapper()
this.legacyImpl = new LegacyImpl();
}
public void wrappedMethod() {
this.legacyImpl.wrappedMethod();
}
}
Related
The structure of my project like the following:
I am sure everything okay but only one thing make the problem is #Autowired in StoredProcedureSpringDataJpaApplication.java like the following:
public class StoredProcedureSpringDataJpaApplication implements CommandLineRunner {
#Autowired
private StudentRepository stu;
public static void main(String[] args) {
SpringApplication.run(StoredProcedureSpringDataJpaApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
// TODO Auto-generated method stub
List<Student> students = stu.findAll();
students.forEach(System.out :: println);
}
}
Error description is:
Field stu in com.example.demo.StoredProcedureSpringDataJpaApplication required a bean of type 'com.repository.StudentRepository' that could not be found.
I know this is familiar question ,I did so many way to try to solve this problem in the internet even in stackoverflow but all can not solve my problem.
Help me solve this problem.
Use #ComponentScan({"com.example.demo", "com.repository"})
By default without this annotation it considers only annotations that exist inside the package where your #SpringBootApplication is declared, aka com.example.demo
Also together with the #ComponentScan use the following
#EnableJpaRepositories(basePackages = {"com.repository"})
Your package structure is incorrect StoredProcedureSpringDataJpaApplication.java should be in the root package. Another way is component scan placing annotation over StoredProcedureSpringDataJpaApplication.java. In your case, it should be like
This won't work for the repository class and as you have a different package structure so #EnableJpaRepositories(basePackages = "com.repository") will help you resolve this issue.
This happens because #SpringBootApplication does only scan in the package where it is defined.
Make sure it is placed at the root of your project and everything that should be scanned below it. For example:
com
- example
- demo
- StoredProcedureSpringDataJpaApplication.java
- repository
- StudentRepository.java
Is there a way to create Java-based configuration class that does exactly same as #ComponentScan(basePackageClasses = {X.class}) ?
I have to create generic configuration class (for extending in tests) doing something like that:
#Configuration
#ComponentScan(basePackageClasses = T.class)
public class EndpointTestConfig<T> {
}
It's impossible to use generics with annotations so I would need the same effect using Java.
I'm not sure what exactly you are trying to achieve. If I understand you correctly you have a base class T and a lot of derived classes? And you want to have a base config that will create common beans and every extender will create a bean of class that extends T? So you can do something like that:
#Configuration
public class BaseTestConfig {
//common beans
}
#Configuration
#Import(BaseTestConfig.class)
public class ConcreteEndpointConfig {
#Bean
public YourDerivedClass bean() {
return new YourDerivedClass();
}
}
I hope that I got your idea. If this is not what you need please elaborate.
I'm new to specifying resource routes in Java, and I'm having issues specifying the route. So far I have one Class which simply extends Application, and one class that reacts to input. What are the routing requirements for these classes? My code below does not work and im trying to figure out why. I've tried to find sources for these, but haven't had much luck.
Can I just use a / for the ApplicationPath? All this class does is extend Application so it can find routes.
Example:
package com.sentiment360.helloworld;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
/**
* JAXActivator is an arbitrary name, what is important is that javax.ws.rs.core.Application is extended
* and the #ApplicationPath annotation is used with a "rest" path. Without this the rest routes linked to
* from index.html would not be found.
*/
#ApplicationPath("/")
public class JAXActivator extends Application {
}
Does each class need to have a declared #Path (or can they all be #Stateless)?
#Path("/helloservice")
public class HelloService {
private static Logger _logger;
public HelloService(){
_logger = Logger.getLogger(HelloService.class.getName());
}
private Connection conn() throws SQLException {...}
}
The short version for #1 is yes.
BUT: behavior is implementation dependent. See https://stackoverflow.com/a/16747253/1063501 for a thorough explanation.
As for #2, yes, you generally need to specify a #Path for every endpoint you want. The fact that it is #Stateless is irrelevant as you'll need a way to address it.
I have developed an SDK that uses a Resource in a rest package:
package com.example.some.package.rest;
...
#Path("/health")
public class HealthResource {
public HealthResource() {
// some code
}
#GET
#Path("/")
#Produces(MediaType.TEXT_HTML)
public Response getHealth() {
// some code to return health
}
}
Then I have another package with an Application implementation:
package com.example.different.package.rest;
...
public class HealthApplication extends Application {
public Set<Object> getSingletons() {
return Sets.<Object> newHashSet(new HealthResource());
}
}
However, this will not work for me. I have to use another wrapper class:
package com.example.different.package.rest;
...
#Path("")
public class WrapperHealthResource extends HealthResource {
public WrapperHealthResource() {
super();
}
}
If I use WrapperHealthResource in the HealthApplication instead of HealthResource, then it works fine.
I think it's pretty useless to have this extra class. How can I get rid of this complexity?
Firstly, I haven't been able to test this on Jersey 1.8 - I only have a 2.7 test harness around. But the API hasn't really changed in this area so you should be OK.
If you only need the Application class to enforce the Singleton of your HealthResource resource and nothing else, then I would just annotate the class with #Singleton and remove your Application class. That's the easiest.
I'm not able to reproduce your issue with 2.7, so this may be an issue with 1.8 (unlikely in this instance) or how you're registering your Application. If you want to post the rest of your code, I might be able to help.
Will
PS - if you're able, upgrade to 2.8.
I've been looking all over Google to find some useful information on how to use Guice/Spring DI in Play Framework 2.1
What I want to do is to Inject several Services in some DAO's and vice versa.
Just need some clarification on this - With play 2.1, do you have to use an # annotation within the routes file for DI?
I've looked at this guide here - https://github.com/playframework/Play20/blob/master/documentation/manual/javaGuide/main/inject/JavaInjection.md
and applied the following steps creating a Global class in app and adding the GUICE dependencies in Build.scala but keep on getting a null pointer exception when invoking on the injected object.
Has anyone been able to get DI working in Play 2.1 using Guice? I've seen examples across the internet but they all seem to be using DI within the controller.
I noticed you are using Java. Here is how I got it to work for injecting into a controller.
First, I created the following 4 classes :
MyController:
package controllers;
import play.mvc.*;
import javax.inject.Inject;
public class MyController extends Controller {
#Inject
private MyInterface myInterface;
public Result someActionMethodThatUsesMyInterface(){
return ok(myInterface.foo());
}
}
MyInterface:
package models;
public interface MyInterface {
String foo();
}
MyImplementation2Inject:
package models;
public class MyImplementation2Inject implements MyInterface {
public String foo() {
return "Hi mom!";
}
}
MyComponentModule:
package modules;
import com.google.inject.AbstractModule;
import models.MyInterface;
import models.MyImplementation2Inject;
public class ComponentModule extends AbstractModule {
#Override
protected void configure() {
bind(MyInterface.class).
to(MyImplementation2Inject.class);
}
}
Now the final part, that took me a silly long time to figure out, was to register the module. You do this by adding the following line to the end of the application.conf file, which is located in the conf directory:
play.modules.enabled += "modules.MyComponentModule"
I hope this was helpful to you. :)
I use cake pattern and my own version of Global overriding getControllerInstance
https://github.com/benjaminparker/play-inject
Cheers
Ben
Sorry, this is a late response, but here's our example
https://github.com/typesafehub/play-guice
Have you tried using some different approach to DI than Guice?
We also tried implementing a project with Guice or Spring but ended in registering our dependencies in objects that implement trait such as:
trait Registry {
def userDao: UserDao
...
}
object Registry {
var current: Registry = _
}
object Environnment {
object Dev extends Registry {
val userDao = ...
//implement your environment for develpment here
}
object Test extends Registry {
val userDao = ...
//implement your ennviroment for tests here e.g. with mock objects
}
}
Another good approach wich might fit for you is the cake pattern (just google for it).