Unannotated methods still added in JConsole (JMX) - java

I have a problem managing a class in JMX. I exposed it to JMX, and set the manageable methods and attributes of my class by adding annotation but when I open my bean in the JConsole it exposed all the methods and it prints me the output like illustrated in the screenshot below :
I can still use my exposed methods without any problems but it's a bit annoying to allways have this error's window popping and to have to scroll down to find my exposed methods.
Here is how I declared my bean :
<bean name="MBeanExporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="beans">
<map>
<entry key="SmartTrade:name=tickEngine" value-ref="aggregationEngine" />
</map>
</property>
</bean>
with aggregationEngine is a reference to my class :
<bean name="aggregationEngine" class="com.smarttrade.tick.engine.TickEngine">
<!-- list of properties .... -->
</bean>
and here a part of my class where you can see that setTickDataReader(..) is not exposed but still appears in the JConsole, and also how I made my annotations for the good methods :
public void setTickDataReader(TickDataReader tickDataReader) {
this.tickDataReader = tickDataReader;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
#ManagedOperation(description = "Activate or deactivate tick data")
#ManagedOperationParameters({ #ManagedOperationParameter(name = "enable", description = "boolean") })
public void enableTickData(boolean enable) {
this.enabled = enable;
if (enabled) {
init();
} else {
unsubscribe();
}
}
Any idea of where it can come from ?
Thanks in advance.

The org.springframework.jmx.export.MBeanExporter by default uses the org.springframework.jmx.export.assembler.SimpleReflectiveMBeanInfoAssembler. Which effectively exposes all the public methods to JMX.
To only have your annotated methods exported either switch to using the org.springframework.jmx.export.annotation.AnnotationMBeanExporter or set the namingStrategy and assembler property in such a way that it uses annotation processing (which is basically what the org.springframework.jmx.export.annotation.AnnotationMBeanExporter also does).

Related

How setter works inside Spring Framework #2?

Sorry for the copy of this article. I'd want to comment it, but without 50 scores of reputation I can`t comment, so...
I have
private boolean stopLoggingIntoDb;
....
public void setStopLoggingIntoDb(String stopLoggingIntoDb) {
this.stopLoggingIntoDb = BooleanUtils.toBoolean(stopLoggingIntoDb.replaceAll("[^A-Za-z]", ""));
logger.warn("Logging into SiebelMethodLogs is " + (!this.stopLoggingIntoDb ? "ON" : "OFF"));
}
and XML
<bean id="siebelMethodProcessor" class="com.entities.utils.Logger">
<property name="logService" ref="logService"/>
<property name="stopLoggingIntoDb" value="${monitor.siebel.stopLogging}"/>
</bean>
In that case, is everything Ok, but If I change the property in setter method from stopLoggingIntoDb to stopLog and change the property name in XML also to stopLog or not, Spring said me Invalid property 'stopLoggingIntoDb' or Bean property 'stopLog' is not writable.
Because of that, my question is What the Spring does with setter method? Which value is injected and which field/property is searching while gets the injection?
As can be seen in this example in the Spring Documentation, the name attribute of the <property> element must match a setter method. The name of the methods parameter and the name of the field doesn't matter.
Examples of dependency injection
The following example uses XML-based configuration metadata for setter-based DI. A small part of a Spring XML configuration file specifies some bean definitions:
<bean id="exampleBean" class="examples.ExampleBean">
<!-- setter injection using the nested ref element -->
<property name="beanOne">
<ref bean="anotherExampleBean"/>
</property>
<!-- setter injection using the neater ref attribute -->
<property name="beanTwo" ref="yetAnotherBean"/>
<property name="integerProperty" value="1"/>
</bean>
<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
public class ExampleBean {
private AnotherBean beanOne;
private YetAnotherBean beanTwo;
private int i;
public void setBeanOne(AnotherBean beanOne) {
this.beanOne = beanOne;
}
public void setBeanTwo(YetAnotherBean beanTwo) {
this.beanTwo = beanTwo;
}
public void setIntegerProperty(int i) {
this.i = i;
}
}
Notice how name="integerProperty" matches up to the setIntegerProperty() method, even though the parameter is named i and the field is named i.

Rest Spring beans using xml Configuration

I am using Rest Spring beans using xml Configuration.
I am trying to access variables which are initailized by beans using REST urls. But i am not able to fetch values. values fetched are null.
Is there anyway to initalize values and keep them intact and access them when i make call using urls.
Please suggest some way.
TIA
Edit:
Model:
#Repository
public class Topic{
private Integer id;
private String name;
//Getter and setter with constructor
}
Controller Class:
#RestController
#Singleton
public class TopicController{
#Autowired
private TopicService topicService;
public void setTopicService(TopicService topicService) {
this.topicService = topicService;
}
#RequestMapping("/topics")
public List<Topic> getAllTopics() {
System.out.println("in get all topics");
return topicService.getAllTopics();
}
}
ServiceClass:
#Service
public class TopicService {
#Autowired
private List<Topic> allTopics ;
public TopicService() {
}
public List<Topic> getAllTopics() {
return allTopics;
}
public void setAllTopics(List<Topic> allTopics) {
this.allTopics = allTopics;
}
}
Bean.xml
<bean name="topicService" id="topicService"
class="org.springtest.service.TopicService">
<property name="allTopics">
<list>
<bean class="org.springtest.model.Topic">
<property name="id" value="20" />
<property name="name" value="topic20" />
</bean>
<bean class="org.springtest.model.Topic">
<property name="id" value="30" />
<property name="name" value="Topic30" />
</bean>
</list>
</property>
</bean>
<bean id="topicController"
class="org.springtest.controller.TopicController"
scope="singleton">
<property name="topicService" ref="topicService"></property>
</bean>
output of
/localhost:8080/topics is:
{"id":null,"name":null}
Main class:
public static void main(String[] args) {
SpringApplication.run(CourseApiApp.class, args);
ApplicationContext context = new
ClassPathXmlApplicationContext("main/resources/Bean.xml");
TopicController tc= new TopicController();
System.out.println(tc.getAllTopics().size());// throwing nullpointerexception as topicService is null
}
I suggest you take a look at Jersey. It's a REST framework, one of the best in my opinion. Be sure to use a Snapshot of the last version of Jersey (I believe it's version 3), as it will have full support of Spring.
It's usage is simple.
A method controller will have 5 lines tops. It also encourages users to the best practices of a RESTful API. Such as defining the location header on a successful post, link headers referencing paging in a collection get, amongst others.
With Maven or Gradle in your project, integrating Jersey will take you 5 minutes.
I use it over Spring because it's sole purpose is implementing a REST API, while Spring has it simply as a feature.
I apologize for my lack of solution, just ask me if you need help getting started.
Andrés
That's because in the main method you have: TopicController tc= new TopicController(); which is wrong. The TopicController should be instantiated by Spring in your Main class using dependency injection. Above the main method you should write
#Autowired
private TopicController tc;, and remove the "tc" variable in the main method.

jackson serialization views: nested object

The following is a snippet from a project based on Spring Boot 1.3. Json serialization is made via Jackson 2.6.3.
I have the following Spring MVC controller:
#RequestMapping(value = "/endpoint", method = RequestMethod.GET, produces=MediaType.APPLICATION_JSON_VALUE)
public Results<Account> getAllAccounts() throws Exception {
return service.getAllAccounts();
}
The returned Results is as follows (getters and setters removed):
public class APIResults<T> {
private Collection<T> data;
}
The Account class is as follows (getters and setters removed):
public class Account {
#JsonView(Views.ViewA.class)
private Long id;
#JsonView(Views.ViewB.class)
private String name;
private String innerName;
}
I also have the following Json Views
public class Views {
public interface ViewA {}
public interface Publisher extends ViewB {}
}
The motive is to return different view from the same controller, based on some predict.
So I'm using AbstractMappingJacksonResponseBodyAdvice to set the view at run-time. When setting bodyContainer.setSerializationView(Views.ViewA.class), I'm getting an empty json result and not a json array of objects that only contains the id property. I suspect this is because the data property in APIResults< T > is not annotated with #JsonView, however shouldn't non annotated properties be included in all views (doc)?
Is there a way to get what i want without adding the #JsonView annotation to APIResults< T > (this is not an option).
I know i can use Jackson mixin to get the functionality i desire, however is there a way to do that using Json views ?
You were right, spring MVC Jackson2ObjectMapperBuilder has been improved to set jackson mapper feature DEFAULT_VIEW_INCLUSION to false, so not annotated property data is not serialized.
To enable the feature, use following config (XML):
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="defaultViewInclusion" value="true"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
With this config, you'll have id and innerName properties serialized when using ViewA view:
{"data":[
{"id":1,"innerName":"one"},
{"id":2,"innerName":"two"},
{"id":3,"innerName":"three"}
]}
Further, you may manage to hide innerName also, by adding some other view annotation to it.

What is the role of Service layer in spring and how do I split my logic in this scenario?

I am trying to write a simple webapp, which takes email id as parameter and generates a token for the user with that id. I think my code is self-explanatory, so I will just paste it here so that I don't have to explain in detail.
This is my controller/servlet code
User user = userManager.getUserByEmailId("xyz#gmail.com");
if (user == null) {
//TODO handle this
}
if (user.getIssuedTokens() == user.getMaxTokens()) {
// TODO handle this
}
String token = tokenService.createToken();
user.setToken(token);
user.setIssuedTokens(user.getIssuedTokens() + 1);
userManager.updateUser(user);
userManager and tokenService are Service layer implementations.
#Service("tokenService")
public class TokenizationServiceImpl implements TokenizationService {
#Autowired
private TokenDAO tokenDAO;
#Transactional
public String createToken() {
String uuid = UUID.randomUUID().toString();
tokenDAO.createToken(uuid);
return uuid;
}
}
#Service("usermanager")
public class UserInterfaceImpl implements UserInterface {
#Autowired
private UserDAO userDAO;
#Transactional
public void createUser() {
userDAO.createUser();
}
public User getUserByEmailId(String emailID) {
return userDAO.getUserByEmailId(emailID);
}
#Transactional
public void updateUser(User user) {
userDAO.updateUser(user);
}
}
my spring configuration is like this
<tx:annotation-driven />
<context:component-scan base-package="com.myapp.dao" />
<context:component-scan base-package="com.myapp.service" />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mydb" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<!-- dataSource TransactionManager -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
Here are my questions:
Does it make sense to inject two services (usermanager and tokenService) into my controller/servlet and then invoke them one after another? Or Should I have written one method in TokenServiceImpl directly, which would make use of usermanager service or UserDAO directly?
The transactional attribute did not seem to work for me. When updateUser method failed, a token was created in the database from createToken() method. What am I doing wrong here? Why did not the transaction rollback?
How do I in general decide on whether my service should use multiple DAOs or other services?
Well, my thoughts about your second question may also answer your first question. Looking to you snippet, I can notice that you are creating two different transactions for tokenService.createToken() and userManager.updateUser(user) since you are calling them from outside a #Transaction method. In order fix this behavior, you gonna need to do something like:
public class UserService {
...
#Transactional
public void assignToken() {
User user = userManager.getUserByEmailId("xyz#gmail.com");
if (user == null) {
//TODO handle this
}
if (user.getIssuedTokens() == user.getMaxTokens()) {
// TODO handle this
}
String token = tokenService.createToken();
user.setToken(token);
user.setIssuedTokens(user.getIssuedTokens() + 1);
userManager.updateUser(user);
}
}
You can notice that, in order to take into account this new transactional behavior, I created a new business component called UserService. Even though I don't really know your application enough to say what is the best approach, I would definitely not let it in your controller. In my opinion, you should isolate this behavior in:
a new business component (as I did in this example)
or encapsulate it inside your UserManager for instance
Now, is up to you decide whether it's worth coupling UserService to TokenizationService or creating a new business class for that. Reading the code you provided, it seems to me that UserService could have a TokenizationService since tokens won't be used in a different context.
Please, let me know your opinions.
Yes, all the code in the controller should be in a transactional service. As is your service doesn't do anything other than delegating to methods of the DAO. The service is supposed to contain the business logic, and to demarcate transactions.
Each of your services is transactional. So, when calling createToken(), a transaction starts and is committed as soon as createToken() returns. And when updateUser() is called, another transaction is started and commits or rollbacks as soon as the updateUser() returns/fails. That's one of the reasons why all the controller code should be in a single transactional service. If that was the case, both calls would be made in a single transaction, and if the second call failed, the whole transaction would be rollbacked, including the token generation.
My rule is: if a service just needs to get data from the database, it should use a DAO. If it needs to reuse business logic already defined in another service, then it should delegate to that service.

Properties Handling With Seam In A Spring-like fashion

One of the Spring features I like the most is how you can handle properties loaded from a file. You only to need to set up a bean like the one below
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/app.properties" />
</bean>
Now you are able to inject the properties values loaded from the app.properties into your beans by using either xml (see below) or annotations.
<bean class="com.example.PersonDaoImpl">
<property name="maxResults" value="${results.max}"/>
</bean>
results.max is one of the properties.
I'm great fan of this feature because it enables me to create quite flexible applications that I can turn on/off some functionality by only changing one property - without redeploying the app.
Now I'm working with JBoss Seam and I've been struggling to find a way to do something similar using this framework.
Does anyone know how to do it? If not, does anyone have any idea of how I could handle properties in a nice way using Seam (I have seen some ways - but none of them were good enough).
Thanks.
If there's no appropriate way using you software stack (is there really no dependency injection!?). I'd say: Use Google Guice (https://code.google.com/p/google-guice/ , https://code.google.com/p/google-guice/wiki/Motivation?tm=6)!
Bad thing with Guice: You may have to read a lot to understand how it works, and what you can do with it. But after it's running you will simply inject your Properties object where you need it:
class YourClass {
#Inject Properties myProperties;
#Inject
public YourClass() { ... }
public void someMethod() {
use the property
}
}
or if you need the properties inside the constructor, you could also do:
class YourClass {
final Properties myProperties;
#Inject
public YourClass(Properties myProperties) {
this.myProperties = myProperties;
}
public void someMethod() {
use the property
}
}
Using Guice maybe enforces you to refactor your whole app.
But if you already have some DI framework, you should simply use that :)

Categories