Please look at the code I posted below. FYI, this is from the Oracle website's websocket sample:
https://netbeans.org/kb/docs/javaee/maven-websocketapi.html
My question is, how does this work?! -- especially, the broadcastFigure function of MyWhiteboard. It is not a abstract function that is overridden and it is not "registered" with another class as in the traditional sense. The only way I see it is when the compiler sees the #OnMessage annotation, it goes and inserts the broadcastFigure call into the compiled code for when a new message is received. But before calling this function, it flows through the received data through the FigureDecoder class - based on this decoder being specified in the annotation #ServerEndpoint. Within broadcastFigure, when sendObject is called, the compiler inserts a reference to FigureEncoder - based on what's specified in the annotation #ServerEndpoint. Is this accurate?
If so, why did this implementation do things this way using annotations? Before looking at this, I would have expected there to be an abstract OnMessage function which needs to be overridden and explicit registration functions for Encoder and Decoder. Instead of such a "traditional" approach, why does the websocket implementation do it via annotations?
Thank you.
Mywhiteboard.java:
#ServerEndpoint(value = "/whiteboardendpoint", encoders = {FigureEncoder.class}, decoders = {FigureDecoder.class})
public class MyWhiteboard {
private static Set<Session> peers = Collections.synchronizedSet(new HashSet<Session>());
#OnMessage
public void broadcastFigure(Figure figure, Session session) throws IOException, EncodeException {
System.out.println("broadcastFigure: " + figure);
for (Session peer : peers) {
if (!peer.equals(session)) {
peer.getBasicRemote().sendObject(figure);
}
}
}
#OnError
public void onError(Throwable t) {
}
#OnClose
public void onClose(Session peer) {
peers.remove(peer);
}
#OnOpen
public void onOpen(Session peer) {
peers.add(peer);
}
}
FigureEncoder.java
public class FigureEncoder implements Encoder.Text<Figure> {
#Override
public String encode(Figure figure) throws EncodeException {
return figure.getJson().toString();
}
#Override
public void init(EndpointConfig config) {
System.out.println("init");
}
#Override
public void destroy() {
System.out.println("destroy");
}
}
FigureDecoder.java:
public class FigureDecoder implements Decoder.Text<Figure> {
#Override
public Figure decode(String string) throws DecodeException {
JsonObject jsonObject = Json.createReader(new StringReader(string)).readObject();
return new Figure(jsonObject);
}
#Override
public boolean willDecode(String string) {
try {
Json.createReader(new StringReader(string)).readObject();
return true;
} catch (JsonException ex) {
ex.printStackTrace();
return false;
}
}
#Override
public void init(EndpointConfig config) {
System.out.println("init");
}
#Override
public void destroy() {
System.out.println("destroy");
}
}
Annotations have their advantages and disadvantages, and there is a lot to say about choosing to create an annotation based API versus a (how you say) "traditional" API using interfaces. I won't go into that since you'll find plenty of wars online.
Used correctly, annotations provide better information about what a class/method's responsibility is. Many prefer annotations and as such they have become a trend and they are used everywhere.
With that out of the way, let's get back to your question:
Why did this implementation do things this way using annotations? Before looking at this, I would have expected there to be an abstract OnMessage function which needs to be overridden and explicit registration functions for Encoder and Decoder. Instead of such a "traditional" approach, why does the websocket implementation do it via annotations?
Actually they don't. Annotation is just a provided way of using the API. If you don't like it then you can do it the old way. Here is from the JSR-356 spec:
There are two main means by which an endpoint can be created. The first means is to implement certain of
the API classes from the Java WebSocket API with the required behavior to handle the endpoint lifecycle,
consume and send messages, publish itself, or connect to a peer. Often, this specification will refer to this
kind of endpoint as a programmatic endpoint. The second means is to decorate a Plain Old Java Object
(POJO) with certain of the annotations from the Java WebSocket API. The implementation then takes these
annotated classes and creates the appropriate objects at runtime to deploy the POJO as a websocket endpoint.
Often, this specification will refer to this kind of endpoint as an
annotated endpoint.
Again, people prefer using annotations and that's what you'll find most of tutorials using, but you can do without them if you want it bad enough.
Related
I am extending AbstractRepositoryEventListener in order to create a md5 hash of an photo and save it with the object.
I'd like to abort saving the photo altogether in the event of an exception.
#Component
public class MyHandler extends AbstractRepositoryEventListener<Photo> {
#Autowired
PhotoService photoService;
#Override
public void onBeforeSave(Photo photo) {
File originalPhoto = new File(foto.getUriOriginal());
try {
String hash = photoService.getHash(originalPhoto);
photo.setHash(hash);
} catch ( IOException | NoSuchAlgorithmException e ) {
e.printStackTrace();
}
}
}
You may throw an instance of RuntimeException. It will get Spring to rollback.
There are other more comprehensive ways, details of which you can find here.
If someone ever have this same problem, here's a better approach.
The goal here is basically to validate an entity.
Spring already provides a ValidatingRepositoryEventListener that uses validators to achieve this goal. Not only will the saving be "aborted", but also the error message will be provided to the client.
It is important to notice that automatic discovery of validators seem to have a bug with a workaround described here.
It is also possible to create custom validation annotations, as described in the link below, resulting in a more reusable code.
In this particular instance, the Validator would look something like this:
#Component("beforeSavePhotoValidator")
public class PhotoValidator implements Validator {
#Override
public boolean supports(Class<?> clazz) {
return Photo.class.equals(clazz);
}
#Override
public void validate(Object obj, Errors errors) {
if (customValidationIsInvalid(obj)){
errors.rejectValue(
"<invalidFieldName>",
"<errorMessageCode>"
);
}
}
}
Observe that:
customValidationIsInvalid, invalidFieldName and errorMessageCode should be appropriately implemented
the errorMessageCode must be set in the ValidationMessages.properties file
the workaround must be implemented, or the validator manually registered
The title might be incorrect, but I will try to explain my issue. My project is a Spring Boot project. I have services which do calls to external REST endpoints.
I have a service method which contains several method calls to other services I have. Every individual method call can be successful or not. Every method call is done to a REST endpoint and there can be issues that for example the webservice is not available or that it throws an unknown exception in rare cases. What ever happens, I need to be able to track which method calls were successful and if any one of them fails, I want to rollback to the original state as if nothing happened, see it a bit as #Transactional annotation. All REST calls are different endpoints and need to be called separately and are from an external party which I don't have influence on. Example:
public MyServiceImpl implements MyService {
#Autowired
private Process1Service;
#Autowired
private Process2Service;
#Autowired
private Process3Service;
#Autowired
private Process4Service;
public void bundledProcess() {
process1Service.createFileRESTcall();
process2Service.addFilePermissionsRESTcall();
process3Service.addFileMetadataRESTcall(); <-- might fail for example
process4Service.addFileTimestampRESTcall();
}
}
If for example process3Service.addFileMetadataRESTcall fails I want to do something like undo (in reverse order) for every step before process3:
process2Service.removeFilePermissionsRESTcall();
process1Service.deleteFileRESTcall();
I read about the Command pattern, but that seems to be used for Undo actions inside an application as a sort of history of actions performed, not inside a Spring web application. Is this correct for my use case too or should I track per method/webservice call if it was successful? Is there a best practice for doing this?
I guess however I track it, I need to know which method call failed and from there on perform my 'undo' method REST calls. Although in theory even these calls might also fail of course.
My main goal is to not have files being created (in my example) which any further processes have not been performed on. It should either be all successful or nothing. A sort of transactional.
Update1: improved pseudo implementation based on comments:
public Process1ServiceImpl implements Process1Service {
public void createFileRESTcall() throws MyException {
// Call an external REST api, pseudo code:
if (REST-call fails) {
throw new MyException("External REST api failed");
}
}
}
public class BundledProcessEvent {
private boolean createFileSuccess;
private boolean addFilePermissionsSuccess;
private boolean addFileMetadataSuccess;
private boolean addFileTimestampSuccess;
// Getters and setters
}
public MyServiceImpl implements MyService {
#Autowired
private Process1Service;
#Autowired
private Process2Service;
#Autowired
private Process3Service;
#Autowired
private Process4Service;
#Autowired
private ApplicationEventPublisher applicationEventPublisher;
#Transactional(rollbackOn = MyException.class)
public void bundledProcess() {
BundleProcessEvent bundleProcessEvent = new BundleProcessEvent();
this.applicationEventPublisher.publishEvent(bundleProcessEvent);
bundleProcessEvent.setCreateFileSuccess = bundprocess1Service.createFileRESTcall();
bundleProcessEvent.setAddFilePermissionsSuccess = process2Service.addFilePermissionsRESTcall();
bundleProcessEvent.setAddFileMetadataSuccess = process3Service.addFileMetadataRESTcall();
bundleProcessEvent.setAddFileTimestampSuccess = process4Service.addFileTimestampRESTcall();
}
#TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK)
public void rollback(BundleProcessEvent bundleProcessEvent) {
// If the last process event is successful, we should not
// be in this rollback method even
//if (bundleProcessEvent.isAddFileTimestampSuccess()) {
// remove timestamp
//}
if (bundleProcessEvent.isAddFileMetadataSuccess()) {
// remove metadata
}
if (bundleProcessEvent.isAddFilePermissionsSuccess()) {
// remove file permissions
}
if (bundleProcessEvent.isCreateFileSuccess()) {
// remove file
}
}
Your operation looks like a transaction, so you can use #Transactional annotation. From your code I can't really tell how you are managing HTTP response calls for each of those operations, but you should consider having your service methods to return them, and then do a rollback depending on response calls. You can create an array of methods like so, but how exactly you want your logic to be is up to you.
private Process[] restCalls = new Process[] {
new Process() { public void call() { process1Service.createFileRESTcall(); } },
new Process() { public void call() { process2Service.addFilePermissionsRESTcall(); } },
new Process() { public void call() { process3Service.addFileMetadataRESTcall(); } },
new Process() { public void call() { process4Service.addFileTimestampRESTcall(); } },
};
interface Process {
void call();
}
#Transactional(rollbackOn = Exception.class)
public void bundledProcess() {
restCalls[0].call();
... // say, see which process returned wrong response code
}
#TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK)
public void rollback() {
// handle rollback according to failed method index
}
Check this article. Might come in handy.
The answer to this question is quite broad. There are various ways to do distributed transactions to go through them all here. However, since you are using Java and Spring, your best bet is to use something like JTA (Java Transaction API), which enables a distributed transactions across multiple services/instances/etc.. Fortunately, Spring Boot supports JTA using either Atomikos or Bitronix. You can read the doc here.
One approach to enable distributed transactions is through a message broker such as JMS, RabbitMQ, Kafka, ActiveMQ, etc. and use a protocol like XA transactions (two-phase commit). In the case of external services that do not support distributed, one approach is to write a wrapper service that understands XA transactions to that external service.
Below is my code snippet:
ServiceImpl.java
#Service
public class ServiceImpl implements Service {
private Response worker(Audit send) throws ArgumentException {
System.out.println("STEP_1");
worker(send.getRequest(), send.getId());
}
private Response worker(Request request, String id) throws ArgumentException {
System.out.println("STEP_2");
try {
//throwing some exception
} catch (Exception e) {
System.out.println("STEP_3");
}
}
}
Now, what I want is whenever NullPointerException is being thrown from method worker(Request request, String id) as shown above I want to perform some specific task. For that I have written an Aspect class which is following:
MyAspect.java
#Aspect
#Component
public class MyAspect{
#Pointcut("com.xyz.myapp.ServiceImpl.worker() && args(request,..)")
private void someOperation(Request request) {}
#Before("someOperation(request)")
public void process(Request request) {
System.out.println("SUCCESS");
}
#AfterThrowing("com.xyz.myapp.ServiceImpl.worker() && args(request,..)")
public void doRecoveryActions() {
System.out.println("EXCEPTION_SUCCESS");
}
}
Current Output:
STEP_1
STEP_2
STEP_3
Desired Output:
STEP_1
STEP_2
STEP_3
SUCCESS
EXCEPTION_SUCCESS
As you can see MyAspect.java is not getting triggered hence NOT printing values.
What can be the reason for this?
Note:
I tried making worker as public classes too but it didn't work.
Also tried changing the name of the methods to eliminate any overloading issue that too didn't work.
Tried various other pointcut expressions all in vain as of now.
In my application there are other aspect classes working absolutely fine.
You made a typical Spring AOP beginner's mistake: You assume that it works for private methods, but as the documentation clearly says, it does not. Spring AOP is based on dynamic proxies, and those only work for public methods when implementing interfaces via JDK proxies and additionally for protected and package-scoped methods when using CGLIB proxies.
You should make the worker() method public if you want to intercept it from an aspect.
P.S.: Full-fledged AspectJ also works for private methods, but to switch to another AOP framework would be overkill here.
Update: You also have other problems in your code:
The first worker method, even if you make it public, does not return anything. The last statement should be return worker(send.getRequest(), send.getId());, not just worker(send.getRequest(), send.getId());.
Your pointcut com.xyz.myapp.ServiceImpl.worker() will never match because it has an empty argument list, but your method has arguments. The args() does not help you here.
The syntax of your pointcut is also wrong because it does not specify a return type for the method, not even *. Furthermore, the method name itself is not enough, it should be enclosed in an actual pointcut type such as execution(). I.e. you want to write something like:
#Pointcut("execution(* com.xyz.myapp.ServiceImpl.worker(..)) && args(request, ..)")
private void someOperation(Request request) {}
To intercept a method that throws an exception you can use this code (works only if methods are public):
#AfterThrowing(pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()",throwing="ex")
public void doRecoveryActions(NullPointerException ex) {
// ...
}
Source: Spring AOP
Say I've got a logging service deployed to some (jaxrs-compliant) container.
#Path("/logger")
public class LogService
{
#GET
#Path("/log")
public Response log(final String #QueryParam("msg") msg)
{
System.out.println(msg);
// ...
}
}
If I make the following request to the container hosting this service, I expect to see the output of my message to the container's stdout log:
GET <host>:<port>/logger/log?msg=foo
Now I'd like to change the implementation of this log message at runtime with behavior specified by some arbitrary client.
For example, say we had an interface:
public interface LoggerApi
{
void logMessage(final String msg);
}
and the service was redefined to use an implementation of this interface:
#Path("/logger")
public class LogService
{
public static LoggerApi LOGGER = new LoggerApi()
{
void logMessage(final String msg)
{
System.out.println(msg);
}
}
#GET
#Path("/log")
public Response log(final String #QueryParam("msg") msg)
{
LOGGER.logMessage(msg);
// ...
}
}
The question thus becomes, how can I hot swap the implementation of logger with a new implementation defined by some client external to the server.
My first instinct was that RMI and/or dynamic proxies could get me where I wanted to be, but I'm not soo sure with all the security policy madness.
Essentially what I want is the ability to do the following:
#Path("/config")
public class ConfigService
{
#POST
#Path("/loggerApi")
public Response setLoggerApi(final LoggerApi clientSuppliedLogger)
{
LogService.LOGGER = clientSuppliedLogger;
// ...
}
}
Thoughts?
(Oh and I know this poses a severe security risk and such a pattern ought never be used in production environments. My interest is in designing a mock service where the service's behavior and side effects can be defined by the integration tests calling the mock service)
I'd like to set up my beans to use both Hibernate Validator (for validation) and Google Guice (for DI and method interception).
Ideally, I'd like to have a setup where any method that "fails" validation will cause a method interceptor to be called:
public class Widget {
#NotNull
public Fizz getFizz() {
return fizz;
}
}
public class FailedWidgetInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
// This gets executed if Widget's getFizz() returns null...
}
}
But it looks like Hibernate Validator only allows you to determine pass/fail status by explicitly passing an object T to a ClassValidator<T>'s getInvalidValues() method.
So I need a place to make such a call! The only viable solution I can think of is to create my own annotation (which I've never done before!) which might look like this:
#NotNull
public #interface AutoValidatingNotNull {
// ...??
}
And then in Guice Module:
public class WidgetModule implements Module {
public void configure(Binder binder) {
binder.bindInterceptor(
any(),
annotatedWith(AutoValidatingNotNull.class),
new ValidatingWidgetInterceptor()
);
}
}
public class ValidatingWidgetInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
ClassValidator<Widget> widgetValidator = new ClassValidator<Widget>();
InvalidValue[] badVals = widgetValidator.getInvalidValues(widget);
if(badVals.length > 0)
handleFailedValidationAndThrowRuntimeExceptionOrSomething();
}
}
Finally, to change getFizz():
#AutoValidatingNotNull
public Fizz getFizz() {
return fizz;
}
For one, this only almost works: inside the interceptor's invoke method, how do I get my hands on the widget instance (the one we wish to validate)?. Is there a way to pass the widget instance via annotations?
Edit:
Doesn't look like I can pass Object into annotations (as parameters)...
Second, this is kind of nasty. Perhaps I'm overlooking something that Hibernate Validator offers that takes care of all this for me? Is there a better way to go? Thanks in advance!
It seems like you're still using the Hibernate Validator 3.x API around ClassValidator et al.
I recommend to upgrade to 4.2 where an API for method validation was introduced which exactly does what you describe.
An example for the required glue code to integrate that API with Google Guice can be found in this project which I created a while ago on GitHub.