I have created this class:
import org.springframework.stereotype.Component;
...
#Component("notTheNameTestMe") //shouldnt this only work with testMe ?
public class TestMe {
public void showMsg() {
System.out.println("Autowiring works");
}
}
And I'm using it this way in a second class (or better: controller):
import com.example.TestMe; //shouldnt this be not necessary with autowire? But getting error else...
...
#Autowired
private TestMe testMe;
...
this.testMe.showMsg();
But this works perfectly (so maybe Im not really using autowire here?), it even works if I rename the whole TestMe class to TestMeSomething (if I adjust the import in the second class)
I dont really understand what #Autowired does. I thought it just scans for SpringBoot Components (which are named by the string in #Component() and when it finds a match it Injects the dependancy. But in my example the match is impossible and I still can see the message "Autowiring works" in the console. This shouldnt be like this if I would really use autowire here or? What am I understanding in a wrong way? What is the difference to using new TestMe() then? I have the dependancy already with the import or? So not a real dependancy injection, or?
Spring is not operating on the name in the #Component annotation. Rather it's using the name of the class. It's simply finding a class named TestMe because that's the type of the variable you've annotated with #Autowired.
Related
a question:
When I do something like:
package path.to.common.package.test;
#BeforeClass
public class CommonTestSetup {
public void setUp() {
// Setup Stiff
}
}
And the other class setup in the same package:
package path.to.common.package.test;
public class TestTest extends CommonTestSetup {
#Test
public void testGetTestReturnsCorrectStrings() {
// do asserts etc
}
}
And then executing JUnit test on testGetTestReturnsCorrectStrings I am getting an error:
org.junit.runners.model.InvalidTestClassError: Invalid test class 'org.junit.runner.manipulation.Filter':
1. No runnable methods
at org.junit.runners.ParentRunner.validate(ParentRunner.java:456)
at org.junit.runners.ParentRunner.<init>(ParentRunner.java:99)
at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:84)
at org.junit.runners.JUnit4.<init>(JUnit4.java:23)
at org.junit.internal.builders.JUnit4Builder.runnerForClass(JUnit4Builder.java:10)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:66)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:37)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:66)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:39)
at org.junit.internal.requests.FilterRequest.getRunner(FilterRequest.java:36)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createFilteredTest(JUnit4TestLoader.java:80)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:71)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:46)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:523)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:761)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:461)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:207)
Why is that? Does it mean JUnit 4 does not support Test classes extending a base class?
The idea behind this was to create a single SetUp base class, shared by many other test classes that need it.
Originally I even tried to have the base class in another package entirely, then moved it to the same package for testing, and got a different error (the one above).
use import org.junit.Test;
instead of import org.junit.jupiter.api.Test;
Based on the JUnit documentation:
Annotating a public static void no-arg method with #BeforeClass causes it to be run once before any of the test methods in the class
So move the #BeforeClass annotation to the setUp method and make into a static method.
You may also check for things like
class classname {
class another class{
}
}
Keep one class in file it helps
I experienced similar ... I hopes it help someone ;-)
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'm using the spring state machine and want to add on functionality to transitions and state changes using #WithStateMachine, #OnTransition and #OnStateChanged to keep the class with #EnableStateMachine as simple as possible. I never got it to work though and after some trial and error I realised that the #WithStateMachine bean has to be created before the state machine but that dependency isn't automatically solved.
The interesting parts of my project basically boils down to the following:
package org.myorg.a
#Component
public class MyComponent {
#Autowired
StateMachine<States, Events> sm;
}
package org.myorg.b
#WithStateMachine
public class Listener {
#OnTransition
public void anyTransition() {}
}
MyComponent and therefore the state machine will be created before the Listener because Spring will look in package a before package b and in effect none of the methods in class Listener will be associated with the state machine and the anyTransition method will never be called.
The only two solutions to this that I can think of is
Rename the packages
Annotate the #EnableStateMachine class with #DependsOn and explicitly depend on all #WithStateMachine classes
In my opinion neither of those two solutions are good. Does anyone have a better way to solve this?
Hopefully this just got fixed in https://github.com/spring-projects/spring-statemachine/issues/232.
Could someone please explain to me why do we need to use the spring's dependency injection when you can just import a java class like:
import com.package.somejavaclass
I just wonder why?
DI and IoC
Dependency Injection (and Inversion of Control) have nothing to do with import. Dependency injection allows you to make runtime decisions instead of compile-time decisions. For example, how your class gets a database Connection. That is configuration over hard-coding.
import
The import statement allows you to not specify the fully-qualifed name of a class. That is, without import java.util.Date; you can still (for example)
System.out.println(new java.util.Date());
Dependency Injection is used to remove need for the code changes and make it possible using configuration only.
I.e., you have
Interface B {
//some methods
}
class X implements B{
// implement some methods of B
}
class Y implements B{
// implement some methods of B
}
// code without using Dependency Injection
class A1{
private B objB = New X();
//remaining code
}
class A2{
private B objB = New X();
//remaining code
}
Note: if you need to change for some reason objB instance with class Y, you need to make code changes in both classes A1 and A2.
// code using Dependency Injection
class A1{
#Autowired
private B objB;
//remaining code
}
class A2{
#Autowired
private B objB;
//remaining code
}
Here you just need to change configuration of creating instances for interface B and change required class from X to Y that's it.
No changes in any of java classes (here A1 and A2).
Import - is static import,
Dependency Injection - dynamic import
In addition to #Nirav Patel answer, I would like to add a scenario. If we want to have a different implementation in different environment (Dev/QA/UAT/Prod), you don't need to change the code, you can achieve it using DI and also changing the configuration in that environment.
Watch this video, if you need a detailed explanation
https://www.udemy.com/spring-framework-video-tutorial/learn/v4/t/lecture/4635190
(By the way, it's a free course in Udemy)
Instructor sends a mock email in dev and real email using smtp, just by changing the configuration.
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).