UPDATED: Added one more question (Question #4).
Hi all,
I'm building myself a custom emailing utility. Now, to obey Single Responsibility Principle, I want to have the following classes: MailerSender, MailProvider and EmailObject. The MailSender is more of a delegate, check it out below:
public class MailSender {
private IMailProvider mailProvider;
public void setMailProvider (IMailProvider provider) {
this.mailProvider = provider;
}
// option to set it up during construction
public MailSender (IMailProvider provider) {
this.mailProvider = provider;
}
public void sendEmail(EmailObject obj) {
if(mailProvider == null)
throw new RuntimeException("Need a mail provider to send email.");
try {
mailProvider.send(obj);
} catch (Exception e) {
// do something here
}
}
}
The MailSender requires an IMailProvider email provider that does the work of sending the email. Find it below:
public interface IMailProvider {
public void sendEmail(EmailObject obj);
}
public class SMTPEmailProvider implements IMailProvider {
public void sendEmail(EmailObject obj) {
// use SMTP to send email using passed-in config
}
}
public class JMSEmailProvider implements IMailProvider {
public void sendEmail(EmailObject obj) {
// push emails to JMS queue to be picked up by another thread
}
}
I have defined a few strategies above, but it can be extended to any number. Since the MailSender can change it's provider at any time, it effectively implements the strategy pattern right?
The EmailObject is a POJO containing relavent email information:
public class EmailObject {
private String to;
private String from;
private String cc;
private String subject;
private String body;
// setters and getters for all
}
Client code will then look like:
MailSender sender = new MailSender(new SMTPMailProvider());
sender.send(new EmailObject());
sender.setMailProvider(new JMSMailProvider());
sender.send(new EmailObject());
My questions are:
1. Have I implemented the Strategy Pattern?
2. Is this design good? Does it make sense for a MailProvider to be aware of an EmailObject?
3. What if I had a new EmailObject later on that required an attachment?
4. The client code now needs to acquire a specific MailProvider before creating a MailSender ... does this make sense?
Ok, let's go through your questions.
1) Vaguely, yes. You could argue that you have "algorithms" or "strategies" and that you can pick between them. However, I prefer to think of the strategy pattern as something that is relevant to algorithms. For example, different ways to get a search result. Here you are dealing with different agents to which you delegate the role of sending email. That's a common design, but I am not sure I would necessarily call it strategy. Either way, design patterns are meant to help you think, not to lock you to a specific name.
2) I think the design is reasonable. I would use interfaces rather than actual classes, especially for the EMailObject. In addition, there should be a factory for email object, don't just new them. It is also very likely that each provider will provide it's own "email object" that includes package detail. You are sending the contents, not the "envelope".
3) That's another good reason to use interfaces rather than a class. And you may want to include getters/setters for metadata and potentially attachments because they are a legitimate part of your domain (an email).
The most important questions here are in my opinion:
Can you test your component without sending actual emails? Yes:
MailSender sender = new MailSender(new FakeMailProvider());
sender.send(new EmailObject());
Can you test your email providers without the rest of the application? Yes:
SMTPMailProvider provider = new SMTPMailProvider();
provider.send(new EmailObject());
You have succesfully decoupled providers from senders.
EDIT: Q4. The client needs to pass the specific MailProvider to the MailSender before sending EmailObject. This statement can be transformed into something like this: "client asks the emailing service to send the email, passing email data and choosing a transport (a way to send an email)". I think it is OK, but if you don't want to specify the transport every time, you may change it to "... the service then sends the email using the configured transport" and move provider instantiation to the configuration.
Related
I have 4 step definition classes and a set of domain object classes.
My first step definition class looks like this:
public class ClaimProcessSteps {
Claim claim;
public ClaimProcessSteps(Claim w){
this.claim = w;
}
#Given("^a claim submitted with different enrolled phone's model$")
public void aClaimSubmittedFromCLIENTSChannelWithDifferentEnrolledPhoneSModel() throws Throwable {
claim = ObjMotherClaim.aClaimWithAssetIVH();
}
}
My Claim class looks like this:
public class Claim {
private String claimType;
private String clientName;
private Customer caller;
private List<Hold> holds;
public Claim() {}
public Claim(String claimType, String clientName, Customer caller) {
this.claimType = claimType;
this.clientName = clientName;
this.caller = caller;
}
public String getClaimType() {
return claimType;
}
My second step definition class looks like:
public class CaseLookupSteps {
Claim claim;
public CaseLookupSteps(Claim w){
this.claim = w;
}
#When("^I access case via (right|left) search$")
public void iAccessCaseInCompassViaRightSearch(String searchVia) throws Throwable {
System.out.println(claim.getClaimType());
}
I've already imported the picocontainter dependency in my POM.XML and I am getting the following error.
3 satisfiable constructors is too many for 'class java.lang.String'. Constructor List:[(Buffer), (Builder), ()]
None of my step definition classes constructors receive primitives as arguments. Does anyone have any clue as to why I am still getting that error? Could it be my business object constructor that does expect a String in its constructor?
Thanks in advance for any help.
Picocontainer looks over not only your step definition classes to resolve dependencies. It also looks over all classes that your steps definitions depend on.
In this case, it's trying to resolve the dependencies for your non-default Claim constructor.
public Claim(String claimType, String clientName, Customer caller) {
...
}
According to this issue there's no way to solve this other than keeping only default constructors in all your dependencies.
Assuming your scenario looks like this:
Given some sort of claim
When I lookup this claim
Then I see this claim
Currently your test is missing the setup step of the claim.
So rather then directly sharing the claim object between steps you should create a ClaimService class with only the default constructor. You can inject this service into your step definitions.
Once you have injected the service, you can use it in the step definition of Given some sort of claim to callclaimService.createSomeSortOfClaim() to create a claim. This claim can be created in memory, in a mock db, actual db, or other persistence medium.
In When I lookup this claim you then use claimService.getClaim() to return that claim so you can use its type to search for it.
Doing it this way you'll avoid the difficulty of trying to make the DI container figure out how it should create the claim under test.
Look at the following use case.
I have a client (Java) application, which wants to get/set the state of another, remote application (C). The communication between them is done via SIP, which is run in another thread.
The SIP interface can do the following:
sendMessage
onRequest
I have two ideas for the architecture:
RPC (JSON-RPC)
Define a class which does the marshalling/unmarshalling for JSONRPCRequests and JSONRPCResponse (http://software.dzhuvinov.com/json-rpc-2.0-base.html)
Define a Invoker class, which has something like a call(server, name, arguments) method.
In the Invoker class, the name and arguments are put into a JSONRPCRequest and sent via the SIP layer sendMessage
Now comes my problem. How do i actually get the right back to the caller? The control flow is now:
The onRequest method is called, but I do now know whether it is the answer to my previous call. What i do is putting all responses reaching my server into a Map, and just poll that list in the Invoker.
A rough sketch might be;
Invoker (provides API to client)
class Invoker {
private Channel channel;
public Invoker(Channel channel) { this.channel = channel; }
public Object call(String server, String name, Object .. args) {
JSONRPCRequest req = ...;
channel.sendMessage(server, req.toString());
while( ! channel.hasResponse(req.id()) {
Thread.sleep(42);
}
return channel.getResponse(req.id()).result();
}
}
Channel (interface to messenger):
class Channel {
private Map<Object, JSONRPCResponse> responses = new //;
private Sip sip = new Sip() {
public void onRequest(String msg) {
JSONRPCResponse response = JSONRPCResponse.parse(msg);
responses.put(msg.id(), response);
}
};
public void sendMessage(String server, String message) {
sip.sendMessage();
}
public boolean hasResponse onRequest(Object id) {
responses.hasKey(id);
}
public JSONRPCResponse getResponse(Object id) {
responses.get(id);
responses.delete(id);
}
}
SIP (messenger itself):
abstract class Sip {
public void sendMessage(String msg) {
// SIP magic
}
public abstract void onRequest(String msg);
}
Is there a better way to do that? My biggest problems/code smells are:
the blocking in Invoker
the protocol is in Invoker, maybe I want to switch marshalling to something else
the map as mean to get the correct response for a request
the SIP abstract method looks strange
No error handling
No timeout
Message Passing
Is there an easy way to get rid of RPC, and implement something like RPC with just message passing? Any hints for pattern are welcome. I do not need the code itself, I am totally fine with just architecture. I tried to google for message passing implementations, and how they actually change state with it, but I did not find anything useful. How to implement timeout/ error handling?
Any good books/literature on that topic is also welcome, as I never programmed such distributed stuff.
Any other ideas on which protocol to use inside SIP to change state is welcome, too, as RPC was my initial thought, and I did not find anything other useful.
The code will not compile, I guess, it was just to visualize my idea.
Define a service interface that has meaningful (for the us case) methods. Instead of using blocking calls, have the client supply a ResponseHandler that will be invoked when the operation is complete:
interface ResponseHandler {
void onComplete(Response response);
void onError(Throwable error);
}
interface SomeService {
void set(String attribute, Object value, ResponsHandler responseHandler);
void get(String attribute, ResponseHandler responseHandler);
}
The implementation of the Service interface can use any suitable protocol, but it has to correlate requests with responses in order to invoke the correct callbacks.
I have a messageListener which purpose is to start clients implementing the Client-interface. The different implementations of the Client-interface is not know at compile time.
The messageListener uses the Launcher-bean to start the clients. So my problem is I need to construct a Launcher-bean that has the selected implementation of the Client-interface injected into it. Im not sure how to do this, or should i approch the problem differently?
public class MyMessageConsumer implements MessageListener {
public void onMessage(Message message) {
String clientType = message.getClientType();
//Here i need to construct a launcher-bean, which has the correct Client-implementation injected
launcher.startClient(message);
}
}
public class Launcher {
#Inject
private Client client;
public void startClient(Message message) {
...
client.start(message);
}
}
edit: I realised that the tricky part is not finding the correct implementation, but that i need the Consumption of a message to happen as a new request. Is it possible to understand what im after?
What you want is a producer.
This way you separate the client of the contextual instance and the producer. So inject them into a producer and have it decide what to use.
For this to be transparent and to avoid ambiguous dependency you could produce a value with #Dynamic qualifier.
#Inject
#Dynamic
Foo foo;
..............................
#Produces
#Dynamic
public Foo getFoo() {
//find out what implementation to use and return it
Creating your own qualifier and producer is very simple to google.
I have this situation:
interface MessageListener
{
void onMessageReceipt(Message message);
}
class MessageReceiver
{
MessageListener listener;
public MessageReceiver(MessageListener listener, other arguments...)
{
this.listener = listener;
}
loop()
{
Message message = nextMessage();
listener.onMessageReceipt(message);
}
}
and I want to avoid the following pattern: (Using the this in the Client constructor)
class Client implements MessageListener
{
MessageReceiver receiver;
MessageSender sender;
public Client(...)
{
receiver = new MessageReceiver(this, other arguments...);
sender = new Sender(...);
}
.
.
.
#Override
public void onMessageReceipt(Message message)
{
if(Message.isGood())
sender.send("Congrtulations");
else
sender.send("Boooooooo");
}
}
The reason why i need the above functionality is because i want to call the sender inside the onMessageReceipt() function, for example to send a reply. But I dont want to pass the sender into a listener, so the only way I can think of is containing the sender in a class that implements the listener, hence the above resulting Client implementation. Is there a way to achive this without the use of 'this' in the constructor? It feels bizare and i dont like it, since i am passing myself to an object(MessageReceiver) before I am fully constructed. On the other hand, the MessageReceiver is not passed from outside, it is constructed inside, but does this 'purifies' the bizarre pattern?
I am seeking for an alternative or an assurance of some kind that this is safe, or situations on which it might backfire on me.
The Client's dependencies (such as MessageReceiver) could be injected into it rather than having the Client know how to construct the MessageReceiver:
Client client = new Client(...);
MessageReceiver rcvr = new MessageReceiver(client, ...);
client.setMessageReceiver(rcvr);
However I would suggest looking into breaking the circular dependency between these two classes, it sounds as if something is off in your design.
The real reason why passing this to another class in the first class's constructor is a bad practice is because you are allowing a reference to this to escape before it is fully constructed.
It wont backfire on you as long as this is never referenced before construction. However, you should never rely on that assumption. Concurrency is a big factor here, as well as the contract for the code you pass it to.
Since Client is a MessageReceiver, why not make it one?
public Client extends MessageReceiver implements MessageListener{
/* ... */
}
I don't see where the MessageReceiver is used, so at the moment you could write the code without MessageReceiver like this and it would be effectively the same:
interface MessageListener
{
void onMessageReceipt(Message message);
}
class Client implements MessageListener
{
MessageSender sender;
public Client(...)
{
sender = new Sender(...);
}
.
.
.
#Override
public void onMessageReceipt(Message message)
{
if(Message.isGood())
sender.send("Congrtulations");
else
sender.send("Boooooooo");
}
}
I think a standard publish-subscribe or Observer pattern is probably what you need - but it's hard to tell without understanding the subtleties of the problem that you are trying to solve.
I'm building an emailing system for a framework I'm developing. Thus far, I've got a generic MailMessage interface that every different type of email message will implement, something along the lines of
public interface MailMessage {
public String[] getTo();
public void setTo(String[] to);
public String getFrom();
public void setFrom(String from);
...
// you can guess the setters/getters here
...
}
I've then got a SimpleMailMessage that's exactly what you would expect as a simple implementation of the interface (no encryption or encoding, just plain text).
I've created an MailMessageFactory interface that's used as an abstract factory. I've got a SimpleMailMessageFactory that implements the factory to produce instances of SimpleMailMessage.
One type of email I'd like to the framework to send is an Alert mail message, that is essentially a regular mail message except with "[Alert]" prefixed to the subject line (Another might be a email containing a "list" of order items, but I'm not sure of where the responsibility falls for converting the list to a String for an email lies). I can either subclass the SimpleMailMessage and override the setSubject(String subject) method to something like
public class AlertMailMessage {
...
public void setSuject(String subject) {
this.to = "[Alert]" + to;
}
...
}
Or I can create a decorator:
public abstract class EmailDecorator implements MailMessage {
protected MailMessage email;
...
// delegate all implemented methods to email
...
}
public class AlertEmailDecorator extends EmailDecorator {
public void setSubject(String subject) {
email.setSubject("[Alert]" + subject);
}
}
Or I can just delegate adding the "[Alert]" string in the SimpleMailMessageFactory.
Thoughts on what I have? I think the problem is that I might be too thoughtful and forward-thinking, but I want the perfect design.
A decorator seems a better option to me. I am thinking of, may be you need to append your subject line with, Fwd: or Re: as well, or may be you need to support signature where you will be adding a signature to the email body.
The decorator seems like the better option. However, why are you writing your own email framework for Java? Why not just use the JavaMail API?
Sounds just like the Spring's support for JavaMail. Don't reinvent the wheel, use already existing, proven solutions, and build on top of that.