-
-
Notifications
You must be signed in to change notification settings - Fork 74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Play2.4 Field Injection always return null MailerClient #78
Comments
Hello @piacia, which version do you use ? |
4.0.0-M1 and play 2.4.2 |
Then I was trying to do something like this: private static SMTPConfiguration smtpConfiguration;
static {
final Configuration root = Configuration.root();
smtpConfiguration = new SMTPConfiguration(root.getString("smtp.host"),
root.getInt("smtp.port"),
root.getBoolean("smtp.ssl"),
root.getBoolean("smtp.tls"),
Option.apply(root.getString("smtp.user")),
Option.apply(root.getString("smtp.password")),
root.getBoolean("smtp.debug"),
Option.apply(root.getInt("smtp.timeout")),
Option.apply(root.getInt("smtp.connectionTimeout")),
root.getBoolean("smtp.mock"));
}
new SMTPMailer(smtpConfiguration).send(email); but could not get it working. Tried all 465, 587, 25 with ssl tls possibilities |
looks like it is because I am using it in models, but not controllers. Is Guice the only way if I want to use mailer in models? |
You can use the static method You can also instantiate a
This should work, do you get an exception ? |
I had the same problem, for some reason injecting the return Play.application().injector().instanceOf(MailerClient.class).send(email); |
This is a problem caused by the constructor:
You can't have a noninjected constructor with a injected field. that is not possible. |
@Mogztter I wouldn't improve the documentation since that is guice specific. The only thing maybe would be a link to the Guice documentation, somewhere. |
Can I just make a comment on this. It look me a while to realise this. I am new to Play! 2,4 (having worked a with 1.x) and the @Inject is new. I created a class to log errors and mail them to an admin address, and this is not a controller, and I got the NullPointerException. Using Play.application().injector().instanceOf(MailerClient.class).send(email); works fine, but that is not clear form the current documentation as it suggests you can inject in any class (I just copied the example class). |
@luukjansen you should avoid What that means is, if you have a class X like that:
if you now try to create the class via |
This might not be the right place to ask, but could you provide an example in Java on how to instantiate a class with the MailerClient correctly? This is all new to me, and I am not getting my head around it yet. I took the example on GitHub, so am trying to figure out how to insatiate this properly without using Play.application(). I tried:
But that doesn't work as MailerClient is abstract. |
Even if this is more Guice related, I think we should add documentation. @luukjansen To answer your question, you can have a look here
|
@Mogztter and how would you do it, I mean setting up a mailer is just: class MyService @Inject()(mailerClient: MailerClient) {
} or on java: class MyService {
private final MailerClient mailerClient;
@Inject
MyService(mailerClient: MailerClient) {
this.mailerClient = mailerClient;
}
} And the Java one is a copy of the guice docs, however thanks to reference.conf we could skip the module creation. The thing is, why it's not working for them is cause they are trying that: Component myComponent = new MyComponent(); which of course would fail since guice doesn't create the instance. |
I think that is exactly the step I am looking for. How do I create an instance using Guice. Injection works in a controller, I have used that before with WS. But how do I instantiate the class and sent an email (e.g like above and in the example) without a controller. I am just not getting it for some reason, I tried following the guise documentation, but am missing something on how to properly instantiate. So e.g. like below (but then to instantiate with guice)
|
@luukjansen you should never create a class which injects something yourself. Which means, you have something like that: public class MyController {
@Inject
private MyService service;
public Result sendMail() {
service.doMail();
return ok("Mail sent!");
}
}
public class MyService {
@Inject
private MailerClient mailerClient;
public void doMail() {
String cid = "1234";
Email email = new Email()
.setSubject("Simple email")
.setFrom("Mister FROM <[email protected]>")
.addTo("Miss TO <[email protected]>")
.addAttachment("attachment.pdf", new File("/some/path/attachment.pdf"))
.addAttachment("data.txt", "data".getBytes(), "text/plain", "Simple data", EmailAttachment.INLINE)
.addAttachment("image.jpg", new File("/some/path/image.jpg"), cid)
.setBodyText("A text message")
.setBodyHtml("<html><body><p>An <b>html</b> message with cid <img src=\"cid:" + cid + "\"></p></body></html>");
mailerClient.send(email);
}
} Now MyService gets injected inside your Controller and MyService gets an instance of mailerClient injected. public ClassX {
@Inject
private MyService myService;
public void sentMail() {
myService.sendEmail();
}
}
// Somewhere else:
public ServiceXYZ {
@Inject
private ClassX classX;
public void doSomething() {
classX.sentMail();
}
} as a rule of thumb, when using DI you should only create data classes yourself, and data classes should never contain a service or something that got injected in any way. |
@schmitch thanks a million, I think it becomes clearer. I implemented the above, and sending message leading back to a controller works fine now. One final question then, and hopefully my difficulty might show difficulties other 'amateurs' might have. I want top sent wanring email to the administrator, so I took the suggestion above to do this in the following way. But you mentioned top avoid to relying on Play.application(). Would that be necessary in such a case though:
This because I fail to create a specific guice injector because the classes are not modules (e.g. implement AbstractModule) yo instantiate the Mails.class through guice. |
Actually you could try to create a LoggerService. Something like that: public class LoggerService {
@Inject
private MailerClient mailerClient;
private Logger logger = new Logger();
public void warn(String msg) {
logger.warn(msg);
}
}
// Class with LoggerService
public class MySuperService {
@Inject
private LoggerService logger;
public void doSomething() {
// do something
logger.warn("there was an error!");
}
} Than you could inject the LoggerService to your services. Is a little bit boilerplate. |
Was following the Java example on home page, use Field injection in Play 2.4. But in debug it seems always have null for
MailerClient
.code looks like this:
The text was updated successfully, but these errors were encountered: