I want to know the purpose of below methods inside the class when the class extends AbstractAnnotationConfigDispatcherServletInitializer
protected Class[] getRootConfigClasses() {
return new Class[0];
}
#Override
protected Class[] getServletConfigClasses() {
return new Class[] { testAPI.class };
}
3.#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
(1) wants a list of #Configuration (user) classes for creating a Root ApplicationContext and (2) wants a list of (user) classes for the AnnotationConfigWebApplicationContext.
So image you have several #Configuration classes coded somewhere, you can register them with:
#Override
protected final Class<?>[] getRootConfigClasses() {
return new Class[]{CoreConfiguration.class, JpaConfiguration.class,
ShiroSecurityConfig.class};
}
Related
I saw a method of using #inject annotation with parameter constructor. I found no use in #module in all parts of the project. I don't understand how this code injects or provides parameters in the constructor.
Can you help me analyze it?
Where is the datamanager provided?
In the whole project, #module + #provide is not used to provide datamanager. I only know that #inject can only annotate the parameterless constructor. I don't know where to instantiate the parameterless datamanager object. Thank you for your help
application:
public class Scallop extends Application {
private ApplicationComponent applicationComponent;
#Override
public void onCreate() {
super.onCreate();
applicationComponent = DaggerApplicationComponent.builder()
.applicationModule(new ApplicationModule(this))
.build();
}
public ApplicationComponent getApplicationComponent() {
return applicationComponent;
}
}
application module:
#Module
public class ApplicationModule {
private Scallop application;
public ApplicationModule(Scallop application) { // 提供类的构造器,传入Applicaton
this.application = application;
}
#Provides
#Singleton
Application provideApplication() {
return application;
}
#Provides
#ApplicationContext
Context provideContext() {
return application;
}
#Provides
#Singleton
Retrofit provideRetrofit() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
return retrofit;
}
#Provides
#Singleton
GankIOService provideGankIOService(Retrofit retrofit) {
return retrofit.create(GankIOService.class);
}
}
#Singleton
#Component(modules = ApplicationModule.class)
public interface ApplicationComponent {
Application getApplication();
DataManager getDataManager();
}
```
one class:
#Singleton
public class DataManager {
private GankIOService gankIOService;
private PreferencesHelper preferencesHelper;
#Inject
public DataManager(GankIOService gankIOService, PreferencesHelper preferencesHelper) {
this.gankIOService = gankIOService;
this.preferencesHelper = preferencesHelper;
}
}
fragment module:
#FragmentScope
#Component(modules = FragmentModule.class, dependencies = ApplicationComponent.class)
public interface FragmentComponent {
void inject(HomeFragment homeFragment);
void inject(GanHuoPageFragment pageFragment);
void inject(XianDuFragment xianDuFragment);
void inject(XianDuPageFragment xianDuPageFragment);
void inject(PicturesFragment picturesFragment);
void inject(MoreFragment moreFragment);
}
#FragmentScope
#Documented
#Scope
#Retention(value = RetentionPolicy.RUNTIME)
public #interface FragmentScope {
}
```
here Can't understand constructor with parameter is #inject
public class GanHuoPagePresenter extends BasePresenter<GanHuoPageContract.View>
implements GanHuoPageContract.Presenter {
private DataManager dataManager;
private Disposable disposable;
#Inject
public GanHuoPagePresenter(DataManager dataManager) { // here here
this.dataManager = dataManager;
}
#Override
public void detachView() {
super.detachView();
if (disposable != null) {
disposable.dispose();
}
}
#Override
public void getGanHuo(String category, final int page) {
final List<GanHuo> ganHuoList = new ArrayList<>();
Observable<BaseResponse<GanHuo>> observable = dataManager.getGanHuo(category, page);
disposable = observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.concatMap(new Function<BaseResponse<GanHuo>, ObservableSource<GanHuo>>() {
#Override
public ObservableSource<GanHuo> apply(#NonNull BaseResponse<GanHuo> ganHuoBaseResponse)
throws Exception {
return Observable.fromIterable(ganHuoBaseResponse.getResults());
}
}).filter(new Predicate<GanHuo>() {
#Override
public boolean test(#NonNull GanHuo ganHuo) throws Exception {
return !ganHuo.getType().equals("福利");
}
}).subscribe(new Consumer<GanHuo>() {
#Override
public void accept(GanHuo ganHuo) throws Exception {
ganHuoList.add(ganHuo);
}
}, new Consumer<Throwable>() {
#Override
public void accept(Throwable throwable) throws Exception {
getView().showError(throwable.getMessage());
}
}, new Action() {
#Override`enter code here`
public void run() throws Exception {
getView().showList(ganHuoList, page);
}
});
}
}
This is how it is used in V in MVP mode:
#Inject GanHuoPagePresenter presenter
That's constructor injection. By marking a constructor with #Inject Dagger knows about the object and can create it when needed. There's no need for modules, e.g. the following is a valid Dagger setup to create some Foo.
public class Foo {
#Inject
public Foo() {}
}
#Component
interface MyComponent {
Foo getFoo();
}
That's not true that #Inject can only annotate the parameterless constructor. From documentation
Injectable constructors are annotated with #Inject and accept zero or more dependencies as arguments.
I found "your" project on Github so let's see where dependencies for GanHuoPagePresenter come from.
#Inject
public GanHuoPagePresenter(DataManager dataManager) {
this.dataManager = dataManager;
}
#Inject
public DataManager(GankIOService gankIOService,PreferencesHelper preferencesHelper){
// gankIOService is provided by ApplicationModule and preferencesHelper uses constructor injection
this.gankIOService = gankIOService;
this.preferencesHelper = preferencesHelper;
}
#Inject
public PreferencesHelper(#ApplicationContext Context context){
// context is provided again by ApplicationModule
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
}
How do I add a Subcomponent to a Module with an argument constructor?
Adding code here in addition to providing a github link:
ExampleApplication.java
public class ExampleApplication extends DaggerApplication {
#Inject
Database database;
#Override
public void onCreate() {
super.onCreate();
Timber.plant(new Timber.DebugTree());
Timber.i(database.name());
}
#Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
return DaggerApplicationComponent
.builder()
.application(this)
.build();
}
}
ApplicationComponent.java
#ApplicationScope
#Component(modules = {
ApplicationModule.class,
AndroidSupportInjectionModule.class,
ActivityBindingModule.class,
DatabaseModule.class,
})
public interface ApplicationComponent extends AndroidInjector<ExampleApplication> {
Database database();
#Component.Builder
interface Builder {
#BindsInstance
Builder application(Application application);
ApplicationComponent build();
}
#Override
void inject(ExampleApplication instance);
}
DatabaseModule.java
#Module(subcomponents = DatabaseComponent.class)
public class DatabaseModule {
#Provides
#ApplicationScope
Database provideDatabase(
#NumberOfCores int numberOfCores,
DatabaseComponent.Builder databaseComponentBuilder) {
return databaseComponentBuilder
.databaseImplModule(new DatabaseImplModule(numberOfCores / 2))
.build()
.database();
}
}
DatabaseComponent.java
#Subcomponent(modules = DatabaseImplModule.class)
public interface DatabaseComponent {
// #PrivateToDatabase <- Is this a qualifier? A scope? Neither?
Database database();
#Subcomponent.Builder
interface Builder {
Builder databaseImplModule(DatabaseImplModule databaseImplModule);
DatabaseComponent build();
}
}
DatabaseImplModule.java
#Module
public class DatabaseImplModule {
DatabaseImplModule(int concurrencyLevel) {}
#Provides DatabaseConnectionPool provideDatabaseConnectionPool() {
return new DatabaseConnectionPool();
}
#Provides DatabaseSchema provideDatabaseSchema() {
return new DatabaseSchema();
}
}
Database.java
public class Database {
#Inject
public Database() { }
public String name() {
return "I have a name";
}
}
I tried to take a look at the dagger subcomponents documentation, specifically the section Subcomponents for encapsulation. I tried to create a code example
to see if I could make it work, but with no luck. Am I missing something in the documentation? (There is a line of code commented out the #PrivateToDatabase which I am not sure what kind of annotation it is).
I have a nano HTTP based web server, that is supposed to delegate its calls to a jersey 2.22.2. On the webserver class constructor I declare an ApplicationHandler as a instance variable:
ApplicationHandler newHandler;
Then in the constructor I initilize it and register a Sample resource class:
Object[] instances = new Object[1];
instances[0] = new SampleResource();
ResourceConfig app = new ResourceConfig();
app.registerInstances(instances);
newHandler = new ApplicationHandler(app);
On the method that processes Http requests I create a ContainerRequest and execute the apply method on the application handler :
SecurityContext secContext = new SecurityContext() {
#Override
public Principal getUserPrincipal() {
return new Principal() {
#Override
public String getName() {
return "user";
}
};
}
#Override
public boolean isUserInRole(String s) {
return true;
}
#Override
public boolean isSecure() {
return true;
}
#Override
public String getAuthenticationScheme() {
return null;
}
};
PropertiesDelegate propertiesDelegate = new PropertiesDelegate() {
Map<String, Object> props = new HashMap<>();
#Override
public Object getProperty(String s) {
return props.get(s);
}
#Override
public Collection<String> getPropertyNames() {
return props.keySet();
}
#Override
public void setProperty(String s, Object o) {
props.put(s, o);
}
#Override
public void removeProperty(String s) {
props.remove(s);
}
};
ContainerRequest request = new ContainerRequest(new URI("http://localhost:2000"), new URI("/test"), session.getMethod().toString(), secContext, propertiesDelegate);
Future<ContainerResponse> responseFuture = newHandler.apply(request);
ContainerResponse response = responseFuture.get();
Object entity = response.getEntity();
Below is the code for the SampleResource class :
public class SampleResource {
#GET
#Path("test")
public Response testMethod() {
return Response.status(Response.Status.OK).build();
}
}
The main reason for doing this is that I want to call a custom API that injects objects into the annotated resource classes.
Stepping through the code, all I get is a NotFoundException.
If you want to inject custom Objects to the resources class you can do that in two waus
using #Context -- By adding your custom object to application context
usign #Inject -- By binding the application to resource config
to use #Context , you need to extend the java.security.Principal object and declare your object fields, and you can instantiate and assign values by using security context.
to user #InJect , you need to register org.glassfish.hk2.utilities.binding.AbstractBinder like below
public class MyApplication extends ResourceConfig {
public MyApplication() {
packages("org.foo.rest;org.bar.rest");
register(new AbstractBinder() {
#Override
protected void configure() {
bindFactory(ObjectThatneedtoInject.class).to(yourClass.class);
}
});
}
}
I'm new to spring mvc and I wish to create a RESTful service.
I create a controller,maps a function to URL and when I try to access it instead of a JSON I receive a 406 error.
I guess there is some trouble with the configuration(Java configuration) but I can't find what it is.
here is my WebConfig:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.yated.web.controller")
public class WebConfig {
}
here is my WebInitializer:
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { WebConfig.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
and here is the controller:
#RestController
public class EventsController {
#RequestMapping(value = "/events")
public List<String> getEvents()
{
List<String> list = new ArrayList<String>();
list.add("Event1");
list.add("Event2");
return list;
}
}
and as I said when I try to access:
http://localhost:8181/web/events
or
http://localhost:8181/web/events.json
I get http error 406
Any ideas?
I try to save a LocalTime (joda) field to the MongoDB with SpringData using spring-boot-starter-parent (org.springframework.boot 1.2.3.RELEASE) and get a StackOverflowError.
The StackOverflowError is in BeanWrapper in the method
public <S> S getProperty(PersistentProperty<?> property, Class<? extends S> type)
Stacktrace:
http-nio-8080-exec-2#5509 daemon, prio=5, in group 'main', status: 'RUNNING'
at org.springframework.data.mapping.model.BeanWrapper.getProperty(BeanWrapper.java:120)
at org.springframework.data.mapping.model.BeanWrapper.getProperty(BeanWrapper.java:100)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$3.doWithPersistentProperty(MappingMongoConverter.java:419)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$3.doWithPersistentProperty(MappingMongoConverter.java:412)
at org.springframework.data.mapping.model.BasicPersistentEntity.doWithProperties(BasicPersistentEntity.java:307)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeInternal(MappingMongoConverter.java:412)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writePropertyInternal(MappingMongoConverter.java:511)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$3.doWithPersistentProperty(MappingMongoConverter.java:424)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$3.doWithPersistentProperty(MappingMongoConverter.java:412)
at org.springframework.data.mapping.model.BasicPersistentEntity.doWithProperties(BasicPersistentEntity.java:307)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeInternal(MappingMongoConverter.java:412)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writePropertyInternal(MappingMongoConverter.java:511)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$3.doWithPersistentProperty(MappingMongoConverter.java:424)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$3.doWithPersistentProperty(MappingMongoConverter.java:412)
at org.springframework.data.mapping.model.BasicPersistentEntity.doWithProperties(BasicPersistentEntity.java:307)...
Adding these two Converters to the CustomConversions fix the problem.
#Configuration
public class MongoConfiguration extends AbstractMongoConfiguration {
#Override
protected String getDatabaseName() {
return "databasename";
}
#Override
public Mongo mongo() throws Exception {
return new MongoClient("localhost");
}
#Override
public CustomConversions customConversions() {
List<Converter<?, ?>> converters = new ArrayList<>();
converters.add(new LocalTimeToStringConverter());
converters.add(new StringToLocalTimeConverter());
return new CustomConversions(converters);
}
}
public class LocalTimeToStringConverter implements Converter<LocalTime, String> {
#Override
public String convert(LocalTime localTime) {
return localTime.toString();
}
}
public class StringToLocalTimeConverter implements Converter<String, LocalTime> {
#Override
public LocalTime convert(String s) {
return LocalTime.parse(s);
}
}