I have an abstract class
public abstract class Sender {
private IThrottler throttler;
public final Object sendMessage(String smsText, String smsSenderName, String contactNumber) throws Exception {
tdLogger.info("sending request >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
String messageId = (String) sendSMS(smsText, smsSenderName, contactNumber);
tdLogger.info("request sent <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
return messageId;
}
public final Object throttleMessage(String smsText, String smsSenderName, String contactNumber) throws Exception {
if (throttler != null) {
throttler.acquire();
tdLogger.info("sending request >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
String messageId = (String) sendSMS(smsText, smsSenderName, contactNumber);
tdLogger.info("request sent <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
return messageId;
} else {
throw new Exception("throttler is not initialized");
}
}
public abstract Object send(String smsText, String smsSenderName, String contactNumber) throws Exception;
}
I have another class SenderImpl that which extends Sender
is there a way to force implementing the function send without giving the ability to call it directly and only be able to call sendMessage and throttleMessage to force running certain logic?
You can make the abstract send method protected so that only subclasses and classes in the same package can call it. This achieves what you intend even if it can be circumvented by placing a class in the same package.
Related
As of Java 9, methods in an interface can be private. A private method
can be static or an instance method. Since private methods can only be
used in the methods of the interface itself, their use is limited to
being helper methods for the other methods of the interface.
Cay S. Horstmann, Core Java Volume I - Fundamentals
I get that we can put the common functionality in the private methods and not make it accessible to public. But we can have two kind of private methods here:
private
private static
Using private static methods is understandable, but when should we use private methods? We are not dealing with instances here as this is an interface, so why creating private methods is allowed? Don't we need only private static methods?
Interfaces are used to define an object's behaviour. This means all of the interface's methods are exposed. When using default methods, we can provide standard implementations of the defined methods, offering code reuse across class boundaries.
In some cases, functionality is required (perhaps just for code reuse in different default methods) but should not be exposed because it would pollute class'/object's namespaces. This is where private default methods come in handy. Examples private default methods could be factories, validations or default state handling.
package com.company;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class Main {
public static void main(final String[] args) {
var messages =
List.of(
MessageQueue.newSubject("Message 1"),
MessageQueue.newTopic("Message 2"),
MessageQueue.newTopic("Message 3"));
final MessageQueueAdapter1 queue1 = () -> messages;
inspectQueue(queue1);
final MessageQueueAdapter2 queue2 = () -> messages;
inspectQueue(queue2);
}
private static void inspectQueue(final MessageQueue queue) {
final List<Message> messagesWithSubject = queue.getMessagesWithSubject();
assert messagesWithSubject.size() == 1 : "expected one message with 'Subject'";
final List<Message> messagesWithTopic = queue.getMessagesWithTopic();
assert messagesWithTopic.size() == 2 : "expected two message with 'Topic'";
assert !queue.getMessages().isEmpty() && 3 == queue.getMessages().size()
: "expected three messages in total";
}
#FunctionalInterface
interface Message {
private static boolean isPrefixedBy(final String message, final String prefix) {
return message != null && !message.isEmpty() && message.startsWith(prefix);
}
default boolean hasSubject() {
return isPrefixedBy(this.getMessage(), MessageQueue.PREFIX_SUBJECT);
}
default boolean hasTopic() {
return isPrefixedBy(this.getMessage(), MessageQueue.PREFIX_TOPIC);
}
String getMessage();
}
interface MessageQueue {
String PREFIX_SUBJECT = "Subject: ";
String PREFIX_TOPIC = "Topic: ";
private static Message newMessage(final String message) {
return () -> message;
}
static Message newSubject(final String message) {
return newMessage(PREFIX_SUBJECT + message);
}
static Message newTopic(final String message) {
return newMessage(PREFIX_TOPIC + message);
}
List<Message> getMessages();
List<Message> getMessagesWithSubject();
List<Message> getMessagesWithTopic();
}
#FunctionalInterface
interface MessageQueueAdapter1 extends MessageQueue {
private static List<Message> filterBy(
final List<Message> messages, final Predicate<Message> predicate) {
return messages.stream().filter(predicate).collect(Collectors.toList());
}
/** {#inheritDoc} */
#Override
default List<Message> getMessagesWithSubject() {
return filterBy(this.getMessages(), Message::hasSubject);
}
/** {#inheritDoc} */
#Override
default List<Message> getMessagesWithTopic() {
return filterBy(this.getMessages(), Message::hasTopic);
}
}
#FunctionalInterface
interface MessageQueueAdapter2 extends MessageQueue {
private List<Message> filterBy(final Predicate<Message> predicate) {
return this.getMessages().stream().filter(predicate).collect(Collectors.toList());
}
/** {#inheritDoc} */
#Override
default List<Message> getMessagesWithSubject() {
return filterBy(Message::hasSubject);
}
/** {#inheritDoc} */
#Override
default List<Message> getMessagesWithTopic() {
return filterBy(Message::hasTopic);
}
}
}
OK, another attempt at actually answering OP's questions. When you need to call another non-static method on the interface from a private method, the private method cannot be static. For example, there would be a compilation error if the private method below was static:
public interface InterfaceWithMethods {
public default void doSomething() {
doSomethingCommon();
}
public default void doSomethingElse() {
doSomethingCommon();
}
public void actuallyDoSomething();
private void doSomethingCommon() {
System.out.println("Do something first.");
actuallyDoSomething();
}
}
I have RESTeasy service. And have implemented simple error handling on methods using try catch and feel something is not very well with it. I've noticed try catch repetition on all my methods. So I want ask way how to avoid repetition (to reduce code size) of try catch but not lost functionality.
#Path("/rest")
#Logged
#Produces("application/json")
public class CounterRestService {
#POST
#Path("/create")
public CounterResponce create(#QueryParam("name") String name) {
try {
CounterService.getInstance().put(name);
return new CounterResponce();
} catch (Exception e){
return new CounterResponce("error", e.getMessage());
}
}
#POST
#Path("/insert")
public CounterResponce create(Counter counter) {
try {
CounterService.getInstance().put(counter);
return new CounterResponce();
} catch (Exception e){
return new CounterResponce("error", e.getMessage());
}
}
#DELETE
#Path("/delete")
public CounterResponce delete(#QueryParam("name") String name) {
try {
CounterService.getInstance().remove(name);
return new CounterResponce();
} catch (Exception e){
return new CounterResponce("error", e.getMessage());
}
}
... // other methods with some try catch pattern
response
public class CounterResponce {
private String status;
#JsonSerialize(include=Inclusion.NON_NULL)
private Object data;
public CounterResponce() {
this.status = "ok";
}
public CounterResponce(Object o) {
this.status = "ok";
this.data = o;
}
public CounterResponce(String status, Object o){
this.status = status;
this.data = o;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
exceptions source
public class CounterService {
private Map<String, StatisticCounter> counters = new HashMap<String, StatisticCounter>();
private static CounterService instance = null;
protected CounterService() {}
public static CounterService getInstance() {
if(instance == null) {
instance = new CounterService();
}
return instance;
}
public StatisticCounter get(String name){
StatisticCounter c = counters.get(name);
if(c == null)throw new IllegalArgumentException("Counter "+name+" not exist");
return c;
}
public void put(String name){
if(name==null)throw new IllegalArgumentException("null can`t be as name");
if(counters.get(name)!=null)throw new IllegalArgumentException("Counter "+name+" exist");
counters.put(name, new Counter(name));
}...
The comments in your question are pointing you in a good direction. Since the answers do not mention it, I'll summarize the general idea in this answer.
Extending WebApplicationException
JAX-RS allows to define direct mapping of Java exceptions to HTTP error responses. By extending WebApplicationException, you can create application specific exceptions that build a HTTP response with the status code and an optional message as the body of the response.
The following exception builds a HTTP response with the 404 status code:
public class CustomerNotFoundException extends WebApplicationException {
/**
* Create a HTTP 404 (Not Found) exception.
*/
public CustomerNotFoundException() {
super(Responses.notFound().build());
}
/**
* Create a HTTP 404 (Not Found) exception.
* #param message the String that is the entity of the 404 response.
*/
public CustomerNotFoundException(String message) {
super(Response.status(Responses.NOT_FOUND).
entity(message).type("text/plain").build());
}
}
WebApplicationException is a RuntimeException and doesn't need to the wrapped in a try-catch block or be declared in a throws clause:
#Path("customers/{customerId}")
public Customer findCustomer(#PathParam("customerId") Long customerId) {
Customer customer = customerService.find(customerId);
if (customer == null) {
throw new CustomerNotFoundException("Customer not found with ID " + customerId);
}
return customer;
}
Creating ExceptionMappers
In other cases it may not be appropriate to throw instances of WebApplicationException, or classes that extend WebApplicationException, and instead it may be preferable to map an existing exception to a response.
For such cases it is possible to use a custom exception mapping provider. The provider must implement the ExceptionMapper<E extends Throwable> interface. For example, the following maps the JAP EntityNotFoundException to a HTTP 404 response:
#Provider
public class EntityNotFoundExceptionMapper
implements ExceptionMapper<EntityNotFoundException> {
#Override
public Response toResponse(EntityNotFoundException ex) {
return Response.status(404).entity(ex.getMessage()).type("text/plain").build();
}
}
When an EntityNotFoundException is thrown, the toResponse(E) method of the EntityNotFoundExceptionMapper instance will be invoked.
The #Provider annotation declares that the class is of interest to the JAX-RS runtime. Such class may be added to the set of classes of the Application instance that is configured.
Introduce a private method such as "apply" which can take function as parameter if you use Java 8. This method will have the error handling and/or mapping, response mapping and response generation code centralized.
From create and delete methods, invoke this apply method and pass the desired counter operation you wish to perform as a lambda expression.
In Class1 we have a method:
public void check(String username, String password) {
if (username and password are correct) {
message = "checked";
} else
{
message = "not checked";
}
}
In Class2 we have a method doPost and then we do this :
Class1 cl = new Class1();
cl.open();
cl.check(username,password);
cl.close()
In class Error I would like to show the message, which is in Class1. Maybe with one Dispatcher? Which is the most efficiency way to make it?
Surely there are much better ways for that, but if you don't want to change your solution as you are setting a message in Class1, you should be able to access to that message in Class2, so create getter and setter for the message variable and access the message via getter(and setters):
in Class1:
public String setMessage(String message){
this.message=message;
}
public String getMessage(){
return message;
}
public void check(String username, String password) {
if (username and password are correct) {
message = "checked";
} else
{
message = "not checked";
}
}
in Class2:
Class1 cl = new Class1();
cl.open();
cl.check(username,password);
cl.close();
out.println(cl.getMessage());//or anything else(you have access to generated message)
You can throw an exception in check() if the check fails.
I have a class
class Message
{
public String message, sender;
public Message (String msg, String from)
{
// check here that msg and from are not null. If so, use a default value or throw an NullPointerException
message = msg;
sender = from;
}
// Just a utility method for printing out the Message to System.out
public String toString () { return sender+":"+message; }
}
I am defining in main activity
Hashtable<String, ArrayList<Message>> table = new Hashtable<String, ArrayList<Message>>();
I want to pass this table variable to another fragment.How can I do this ?
Use Interface & have custom listeners.
Communicating with Other Fragments
I'm getting some weirdness when I'm casting a Dynamic Proxy Class to the object I want it to be. At runtime, under certain conditions, I receive a ClassCastException.
In order to explain this better, here are the definitions for the classes/interfaces I want to use. Brackets have been put around any extended interfaces that (should be) irrelevant.
public interface CommandSender (extends Permissible)
public interface ConsoleCommandSender extends CommandSender, (Conversable)
public interface Player extends (HumanEntity, Conversable), CommandSender, (OfflinePlayer, PluginMessageRecipient)
Full Javadocs can be found here: http://jd.bukkit.org/apidocs/org/bukkit/command/CommandSender.html
Now, here is the code for my proxy class:
public class CommandSignsMessagingProxy implements InvocationHandler {
private Object sender;
private Object receiver;
private boolean silent;
public static Object newInstance(Object proxy) {
return newInstance(proxy, proxy, false);
}
public static Object newInstance(Object proxy, boolean silent) {
return newInstance(proxy, proxy, silent);
}
public static Object newInstance(Object sender, Object receiver) {
return newInstance(sender, receiver, false);
}
public static Object newInstance(Object sender, Object receiver, boolean silent) {
return Proxy.newProxyInstance(
sender.getClass().getClassLoader(),
sender.getClass().getInterfaces(),
new CommandSignsMessagingProxy(sender, receiver, silent));
}
private CommandSignsMessagingProxy(Object sender, Object receiver, boolean silent) {
this.sender = sender;
this.receiver = receiver;
this.silent = silent;
}
// Is called whenever a method is invoked
public Object invoke(Object p, Method m, Object[] args) throws Throwable {
Object result = null;
try {
String name = m.getName();
// If the receiver is being sent a message, only do so if the silent flag is not set
if (name == "sendMessage" || name == "sendRawMessage") {
if (!silent && receiver != null)
result = m.invoke(receiver, args);
} else {
result = m.invoke(sender, args);
}
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException("Unexpected invocation exception: " + e.getMessage());
}
return result;
}
}
And here is a fully working instance of the class:
Player proxy = (Player)CommandSignsMessagingProxy.newInstance(player, false);
proxy.sendMessage("Hi! Silent is turned off, so you can see this!");
proxy.setOp(true);
proxy.other_stuff();
Yet, this one doesn't work:
ConsoleCommandSender ccs = plugin.getServer().getConsoleSender();
CommandSender cs = (CommandSender)CommandSignsMessagingProxy.newInstance(ccs, false);
At run time, this example would produce the following:
java.lang.ClassCastException: $Proxy18 cannot be cast to org.bukkit.command.CommandSender
The created proxy class need to pass the interfaces it suppose to implement,
return Proxy.newProxyInstance(
sender.getClass().getClassLoader(),
sender.getClass().getInterfaces(),
new CommandSignsMessagingProxy(sender, receiver, silent));
failure seems to happen because CommandSender interface may not be returned from the call sender.getClass().getInterfaces() method. So try to see if it properly passes by debugging. If not try sending the interface manually to the method and see if it works.