How to define new metrics for custom Processor (and make them available in jconsole)? - jmx

i have a processor which should produce kstream JMX metrics:
public class ProcessorJMX implements Processor<String, GenericRecord> {
private StreamsMetrics streamsMetrics;
private Sensor sensorStartTs;
#Override
public void init(ProcessorContext processorContext) {
streamsMetrics = processorContext.metrics();
sensorStartTs = streamsMetrics.addSensor("start_ts", Sensor.RecordingLevel.INFO);
}
#Override
public void process(String key, GenericRecord val) {
streamsMetrics.recordThroughput(sensorStartTs, Long.valueOf(val.get("start_ts").toString()));
}
#Override
public void punctuate(long l) { }
#Override
public void close() { }
}
then i use this on my output topic and start my integration test. but when i look in jconsole, i dont see this metric anywhere. where can i find it in jconsole under MBeans?
do i have to do something else before it becomes visible?
here are the properties i am using:
Properties testProperties = new Properties();
testProperties.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG,
CLUSTER.bootstrapServers());
testProperties.put("confluent.metrics.reporter.bootstrap.servers", CLUSTER.bootstrapServers());
testProperties.put("metrics.recording.level", "DEBUG");
testProperties.put("metric.reporters", "org.apache.kafka.common.metrics.JmxReporter");
what is wrong with this config?

The following is what I added to the init:
#Override
public void init(ProcessorContext processorContext) {
streamsMetrics = processorContext.metrics();
Map<String, String> metricTags = new HashMap<String, String>();
metricTags.put("metricTagKey", "metricsTagVal");
MetricConfig metricConfig = new MetricConfig().tags(metricTags);
Metrics metrics = new Metrics(metricConfig);
sensorStartTs = metrics.sensor("start_ts");
MetricName metricName = metrics.metricName("x-name", "x-group", "x-description");
sensorStartTs = streamsMetrics.addSensor("start_ts", Sensor.RecordingLevel.INFO);
sensorStartTs.add(metricName, new Min());
}
This MetricName class helped.

Related

Is there an solution for java.lang.IllegalStateException: Reply already submitted

I want to use pusher sdk in Flutter from android native code because its library no yet completely supported in flutter but when i send first message it received it successfully the next message make app crush with Reply already submitted error her on this line result.success(txt);
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "demo.gawkat.com/info";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler((methodCall, result) -> {
final Map<String, Object> arguments = methodCall.arguments();
if (methodCall.method.equals("getMessage")) {
Pusher pusher = new Pusher("faa685e4bb3003eb825c");
pusher.connect();
Channel channel = pusher.subscribe("messages");
channel.bind("new_message", (channelName, eventName, data) -> runOnUiThread(() -> {
Gson gson = new Gson();
Message message = gson.fromJson(data, Message.class);
String txt = message.text;
result.success(txt);
}));
}
});
}
}
Flutter code:
Future<String> _getMessage() async {
String value;
try {
value = await platform.invokeMethod('getMessage');
} catch (e) {
print(e);
}
return value;
}
Error is
FATAL EXCEPTION: main
Process: com.example.flutter_app, PID: 6296
java.lang.IllegalStateException: Reply already submitted
at io.flutter.view.FlutterNativeView$PlatformMessageHandlerImpl$1.reply(FlutterNativeView.java:197)
at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler$1.success(MethodChannel.java:204)
at com.example.flutter_app.MainActivity.lambda$null$0(MainActivity.java:40)
at com.example.flutter_app.-$$Lambda$MainActivity$axbDTe2B0rhavWD22s4E8-fuCaQ.run(Unknown Source:4)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767
I think it is happening after Flutter upgrade > 1.5.4.hotfix.
Anyway, Yes there is a solution (Refer this github issue),
In your Activitybelow onCreate() add this class:
private static class MethodResultWrapper implements MethodChannel.Result {
private MethodChannel.Result methodResult;
private Handler handler;
MethodResultWrapper(MethodChannel.Result result) {
methodResult = result;
handler = new Handler(Looper.getMainLooper());
}
#Override
public void success(final Object result) {
handler.post(
new Runnable() {
#Override
public void run() {
methodResult.success(result);
}
});
}
#Override
public void error(
final String errorCode, final String errorMessage, final Object errorDetails) {
handler.post(
new Runnable() {
#Override
public void run() {
methodResult.error(errorCode, errorMessage, errorDetails);
}
});
}
#Override
public void notImplemented() {
handler.post(
new Runnable() {
#Override
public void run() {
methodResult.notImplemented();
}
});
}
}
Then, instead of using MethodChannel result to setMethodCallHandler argument callback add name as rawResult and then inside that callback, add this line:
MethodChannel.Result result = new MethodResultWrapper(rawResult);
As below:
//......
new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
(call, rawResult) -> {
MethodChannel.Result result = new MethodResultWrapper(rawResult);
//.....
I use flags for this problem.
Just make sure that methods of same channels are called simultaneously.
The problem seem to appear then.
If two methods needs to be called simulatenously without any problem define both methods in 2 different channels
var resultMap = Map<String, MethodChannel.Result> = HashMap()
new MethodChannel(getFlutterView(), CHANNEL_1).setMethodCallHandler((methodCall, result) -> {
final Map<String, Object> arguments = methodCall.arguments();
if (methodCall.method.equals("method1")) {
// implement method 1
}
});
new MethodChannel(getFlutterView(), CHANNEL_2).setMethodCallHandler((methodCall, result) -> {
final Map<String, Object> arguments = methodCall.arguments();
if (methodCall.method.equals("method2")) {
resultMap = resultMap + mapOf(CHANNEL_2 to MethodResultWrapper(result) // use this later to return result
// implement method2
result.success(true) // or whatever value
}
});
This reduce the chance of "Reply already submitted" error.
Incase if you are using MethodResultWrapper as #Blasanka answer use flags before result.success
when method is invoked set flag to true
val methodCheckFlag: Boolean = true
then when result need to be returned
if(methodCheckFlag) {
methodCheckFlag = false;
methodWrapperResult?.success(true) // or what ever value to return
}
or use the saved MethodResultWrapper as
if(methodCheckFlag) {
methodCheckFlag = false;
resultMap[CHANNEL_2]?.success(true) // or what ever value to return
}

RabbitListenerConfigureIntegrationTests Example

I am looking for some integration test examples for RabbitListenerConfigurer and RabbitListenerEndpointRegistrar and calling #rabbitListner annotation and test the message conversion and pass additional paramenters such as Channel and message properties etc.
Some thing like this
#RunWith(SpringJUnit4ClassRunner.class)
public class RabbitListenerConfigureIntegrationTests {
public final String sampleMessage="{\"ORCH_KEY\":{\"inputMap\":{},\"outputMap\":{\"activityId\":\"10001002\",\"activityStatus\":\"SUCCESS\"}}}";
#Test
public void testRabiitListenerConfigurer() throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
EnableRabbitConfigWithCustomConversion.class);
RabbitListenerConfigurer registrar = ctx.getBean(RabbitListenerConfigurer.class);
/* I want to get the Listener instance here */
Message message = MessageBuilder.withBody(sampleMessage.getBytes())
.andProperties(MessagePropertiesBuilder.newInstance()
.setContentType("application/json")
.build())
.build();
/* call listener.onmessage(message) and that intern pass the call back to #rabbit listener and by that time MessageHandler which is registered should kick off and convert the message */
}
#Configuration
#EnableRabbit
public static class EnableRabbitConfigWithCustomConversion implements RabbitListenerConfigurer {
#Override
public void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) {
registrar.setMessageHandlerMethodFactory(messageHandlerMethodFactory());
}
#Bean
public ConnectionFactory mockConnectionFactory() {
return mock(ConnectionFactory.class);
}
#Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(mockConnectionFactory());
factory.setAutoStartup(false);
return factory;
}
#Bean
MessageHandlerMethodFactory messageHandlerMethodFactory() {
DefaultMessageHandlerMethodFactory messageHandlerMethodFactory = new DefaultMessageHandlerMethodFactory();
messageHandlerMethodFactory.setMessageConverter(consumerJackson2MessageConverter());
return messageHandlerMethodFactory;
}
#Bean
public MappingJackson2MessageConverter consumerJackson2MessageConverter() {
return new MappingJackson2MessageConverter();
}
#Bean
public Listener messageListener1() {
return new Listener();
}
}
public class Listener {
#RabbitListener(queues = "QUEUE")
public void listen(ExchangeDTO dto, Channel chanel) {
System.out.println("Result:" + dto.getClass() + ":" + dto.toString());
/*ExchangeDTO dto = (ExchangeDTO)messageConverter.fromMessage(message);
System.out.println("dto:"+dto);*/
}
}
EDIT 2
I am not getting Exchange DTO populated with values. instead I get Null values
Here is Log :
15:00:50.994 [main] DEBUG org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter - Processing [GenericMessage [payload=byte[93], headers={contentType=application/json, id=8bf86bf1-7e45-d136-9126-69959f92f100, timestamp=1552680050993}]]
Result:class com.dsicover.dftp.scrubber.subscriber.ExchangeDTO:DTO [inputMap={}, outputMap={}]
public class ExchangeDTO implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private HashMap<String, Object> inputMap = new HashMap<String, Object>();
private HashMap<String, Object> outputMap = new HashMap<String, Object>();
public HashMap<String, Object> getInputMap() {
return inputMap;
}
public void setInputMap(HashMap<String, Object> inputMap) {
this.inputMap = inputMap;
}
public HashMap<String, Object> getOutputMap() {
return outputMap;
}
public void setOutputMap(HashMap<String, Object> outputMap) {
this.outputMap = outputMap;
}
#Override
public String toString() {
return "DTO [inputMap=" + this.inputMap + ", outputMap=" + this.outputMap + "]";
}
}
Is there any thing i am missing in Jackson2MessageConverter.
Give the #RabbitListener an id
RabbitListenerEndpointRegistry.getListenerContainer(id);
cast container to AbstractMessageListenerContainer
container.getMessageListener()
cast listener to ChannelAwareMessageListener
call onMessage().
use a mock channel and verify expected call
EDIT
#Autowired
private RabbitListenerEndpointRegistry registry;
#Test
public void test() throws Exception {
AbstractMessageListenerContainer listenerContainer =
(AbstractMessageListenerContainer) this.registry.getListenerContainer("foo");
ChannelAwareMessageListener listener =
(ChannelAwareMessageListener) listenerContainer.getMessageListener();
Channel channel = mock(Channel.class);
listener.onMessage(new Message("foo".getBytes(),
MessagePropertiesBuilder
.newInstance()
.setDeliveryTag(42L)
.build()), channel);
verify(channel).basicAck(42L, false);
}
EDIT2
Your json does not look like a DTO, it looks like a Map<String, DTO>.
This works fine for me...
#SpringBootApplication
public class So55188061Application {
public static void main(String[] args) {
SpringApplication.run(So55188061Application.class, args);
}
#RabbitListener(id = "foo", queues = "foo")
public void listen(Map<String, Foo> in, Channel channel, #Header(AmqpHeaders.DELIVERY_TAG) long tag) throws IOException {
System.out.println(in);
channel.basicAck(tag, false);
}
#Bean
public MessageConverter converter() {
return new Jackson2JsonMessageConverter();
}
public static class Foo {
private HashMap<String, Object> inputMap = new HashMap<String, Object>();
private HashMap<String, Object> outputMap = new HashMap<String, Object>();
public HashMap<String, Object> getInputMap() {
return this.inputMap;
}
public void setInputMap(HashMap<String, Object> inputMap) {
this.inputMap = inputMap;
}
public HashMap<String, Object> getOutputMap() {
return this.outputMap;
}
public void setOutputMap(HashMap<String, Object> outputMap) {
this.outputMap = outputMap;
}
#Override
public String toString() {
return "Foo [inputMap=" + this.inputMap + ", outputMap=" + this.outputMap + "]";
}
}
}
and
#RunWith(SpringRunner.class)
#SpringBootTest
public class So55188061ApplicationTests {
public final String sampleMessage =
"{\"ORCH_KEY\":{\"inputMap\":{},"
+ "\"outputMap\":{\"activityId\":\"10001002\",\"activityStatus\":\"SUCCESS\"}}}";
#Autowired
private RabbitListenerEndpointRegistry registry;
#Test
public void test() throws Exception {
AbstractMessageListenerContainer listenerContainer = (AbstractMessageListenerContainer) this.registry
.getListenerContainer("foo");
ChannelAwareMessageListener listener = (ChannelAwareMessageListener) listenerContainer.getMessageListener();
Channel channel = mock(Channel.class);
listener.onMessage(MessageBuilder.withBody(sampleMessage.getBytes())
.andProperties(MessagePropertiesBuilder.newInstance()
.setContentType("application/json")
.setDeliveryTag(42L)
.build())
.build(),
channel);
verify(channel).basicAck(42L, false);
}
}
and
{ORCH_KEY=Foo [inputMap={}, outputMap={activityId=10001002, activityStatus=SUCCESS}]}
According to your complex requirement to have everything on board, I don't see how we can make a deal with the mock(ConnectionFactory.class). We would need to mock much more to have everything working.
Instead, I would suggest to take a look into the real integration test against existing RabbitMQ or at least embedded QPid.
In addition you may consider to use a #RabbitListenerTest to spy your #RabbitListener invocation without interfering your production code.
More info is in the Reference Manual: https://docs.spring.io/spring-amqp/docs/2.1.4.RELEASE/reference/#test-harness

Can queryEqual() be used to compare with an Array? [duplicate]

How do I query SQL IN clause in Firebase Android? I want to use it in a Firebase Recycler adapter to retrieve only some children based on some condition. Something like the following statement:
SQL----> select * from posts where city in(10 cities comes here)
I need a Firebase query to use that in the Firebase Recycler adapter.
The Firebase database does not have the equivalent of SQL's WHERE id IN (1,2,3). In the case of selecting by ID, Firebase's way of retrieving items is equally fast because Firebase pipelines the requests.
Your case is different though, since you're not selecting by ID. Unfortunately there is no way to directly map your query to a equivalent on the Firebase Database.
Instead of trying to make Firebase's NoSQL database do SQL tricks, I highly recommend that you start mapping your data model to something that fits better with a NoSQL database. Some great resources to kick start this process are this article on NoSQL data modeling and our new video series on Firebase for SQL developers.
Also see Firebase complex "contain" queries
I found the solution: we cannot use FirebaseRecyclerAdapter. Instead we have to create custom adapter that extends RecyclerView.ViewHolder.
For passing values to this adapter, first we have to retrieve data using addValueEventListener and then we have to pass values to our adapter.
This is my code...
final ArrayList<Timeline> timelines = new ArrayList<>();
mDatabaseTimeline.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
final Timeline timeline = dataSnapshot.getValue(Timeline.class);
if(timeline != null){
mDatabaseFriends.child(mAuth.getCurrentUser().getUid()).child("active").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (mAuth.getCurrentUser().getUid().equals(timeline.getUid()) || dataSnapshot.hasChild(timeline.getUid())) {
timelines.add(timeline);
mTimelineRecycler.setAdapter(new RecyclerAdapter(TimelineFragment.this.getContext(), timelines));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
adapter----->
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
Context context;
ArrayList<Timeline> timeline;
public RecyclerAdapter(Context context, ArrayList<Timeline> timeline) {
this.context = context;
this.timeline = timeline;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
View row = inflater.inflate(R.layout.timeline_row, parent, false);
TimelineViewHolder holder = new TimelineViewHolder(row);
return holder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final String post_key = timeline.get(position).getPostkey();
((TimelineViewHolder) holder).setUsername(timeline.get(position).getUsername());
}
#Override
public int getItemCount() {
return timeline.size();
}
public class TimelineViewHolder extends RecyclerView.ViewHolder {
public TimelineViewHolder(View itemView) {
super(itemView);
view = itemView;
}
public View getView() {
return view;
}
public void setUsername(String username) {
TextView usernameTxtView = (TextView) view.findViewById(R.id.timeline_username);
usernameTxtView.setText(username);
}
}
}

Commit EntityManager Transaction using #Transactional - Guice

I'm using Guice to Inject EntityManager.
When I commit the trasaction of the injected entityManager there is nothing happend in the BD side : no transaction passed !!! can you help me to figure out what is going on ?
Here is my code :
Web.xml
<filter>
<filter-name>guiceFilter</filter-name>
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>guiceFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>ca.products.services.InjectorListener</listener-class>
</listener>
The InjectorListener class :
public class InjectorListener extends GuiceServletContextListener {
#Override
protected Injector getInjector() {
return Guice.createInjector(
new PersistenceModule(),
new GuiceModule(),
new RestModule());
}
}
The persistenceModule class :
public class PersistenceModule implements Module {
#Override
public void configure(Binder binder) {
binder
.install(new JpaPersistModule("manager1")
.properties(getPersistenceProperties()));
binder.bind(PersistenceInitializer.class).asEagerSingleton();
}
private static Properties getPersistenceProperties() {
Properties properties = new Properties();
properties.put("hibernate.connection.driver_class", "org.postgresql.Driver");
properties.put("hibernate.connection.url", "jdbc:postgresql://localhost:5432/postgres");
properties.put("hibernate.connection.username", "postgres");
properties.put("hibernate.connection.password", "postgres");
properties.put("hibernate.connection.pool_size", "1");
properties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
properties.put("hibernate.hbm2ddl.auto", "create");
return properties;
}
}
The GuiceModule class :
public class GuiceModule extends AbstractModule {
#Override
protected void configure() {
bind(MemberRepository.class).to(MemberRepositoryImp.class);
bind(ProductRepository.class).to(ProductRepositoryImpl.class);
bind(ShoppingBagRepository.class).to(ShoppingBagRepositoryImpl.class);
}
}
The RestModule class :
public class RestModule extends JerseyServletModule {
#Override
protected void configureServlets() {
HashMap<String, String> params = new HashMap<>();
params.put(PackagesResourceConfig.PROPERTY_PACKAGES, "ca.products.services");
params.put(JSONConfiguration.FEATURE_POJO_MAPPING, "true");
params.put(ResourceConfig.FEATURE_DISABLE_WADL, "true");
serve("/*").with(GuiceContainer.class, params);
}
}
and Finally the webservice (jeresy) call:
#Inject
private Provider<EntityManager> em;
#GET
#Transactional
#Path("/reset")
public void resetData() {
logger.info("Processing reset");
try {
em.get().getTransaction().begin();
for (int i = 0; i < 10; i++) {
em.get().persist(new Product("Product_" + i, "Desc_" + i));
}
em.get().flush();
em.get().getTransaction().commit();
} catch (Exception e) {
throw new WebApplicationException(Response.Status.FORBIDDEN);
}
}
You probably need to add the a persist filter. This will also keep you from having to manage transactions manually. If you do not use the filter you can still inject the UnitOfWork to create transactions. If you are using jpa persist you should not be managing userTransactions.
This is a custom filter that also adds a Lifecycle which it automatically started on startup with some custom code and a map binder builder. It is only there for thoroughness. It is not part of the guice api but more similar to spring's Lifecycle listener. I don't have any spring dependencies at all.
#Singleton
public final class JpaPersistFilter implements Filter {
private final UnitOfWork unitOfWork;
private final PersistServiceLifecycle persistService;
#Inject
public JpaPersistFilter(UnitOfWork unitOfWork, PersistServiceLifecycle persistService) {
this.unitOfWork = unitOfWork;
this.persistService = persistService;
}
public void init(FilterConfig filterConfig) throws ServletException {
// persistService.start();
}
public void destroy() {
persistService.stop();
}
public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
final FilterChain filterChain) throws IOException, ServletException {
unitOfWork.begin();
try {
filterChain.doFilter(servletRequest, servletResponse);
} finally {
unitOfWork.end();
}
}
/**
* Extra lifecycle handler for starting and stopping the service. This
* allows us to register a {#link Lifecycle} with the
* {#link LifecycleListener} and not have to worry about the service being
* started twice.
*
* #author chinshaw
*
*/
#Singleton
public static class PersistServiceLifecycle implements Lifecycle {
private final PersistService persistService;
private volatile boolean isStarted = false;
#Inject
public PersistServiceLifecycle(PersistService persistSerivce) {
this.persistService = persistSerivce;
}
#Override
public boolean isRunning() {
return isStarted;
}
#Override
public void start() {
if (!isStarted) {
persistService.start();
isStarted = true;
}
}
#Override
public void stop() {
persistService.stop();
isStarted = false;
}
}
}
Example of adding filter to module.
#Override
protected void configureServlets() {
filter("/api/*").through(JpaPersistFilter.class);
}
Example of using unit of work to manage the transaction.
#Inject
UnitOfWork unitOfWork;
public void doSomething() {
unitOfWork.begin();
try {
dao.saveState(someobject);
} finally {
unitOfWork.end();
}
}

How to change the main view of a Vaadin 7 application?

I want to write a Vaadin 7 application (see MyVaadinUI below), which asks the user to enter user name and password.
If they are correct, another view (see MainUI below) should appear and take the entire area (replace the login view).
I tried to implement this transition in the method MyVaadinUI.goToMainWindow, but I get the error
java.lang.RuntimeException: Component must be attached to a session when getConnectorId() is called for the first time
at com.vaadin.server.AbstractClientConnector.getConnectorId(AbstractClientConnector.java:417)
at com.vaadin.server.communication.ConnectorHierarchyWriter.write(ConnectorHierarchyWriter.java:67)
at com.vaadin.server.communication.UidlWriter.write(UidlWriter.java:143)
at com.vaadin.server.communication.UidlRequestHandler.writeUidl(UidlRequestHandler.java:149)
at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:97)
at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:37)
at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1371)
at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:238)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
when I run the application and press the button.
How can I fix it?
#Theme("mytheme")
#SuppressWarnings("serial")
public class MyVaadinUI extends UI
{
private TextField userNameTextField;
private PasswordField passwordTextField;
#WebServlet(value = "/*", asyncSupported = true)
#VaadinServletConfiguration(productionMode = false, ui = MyVaadinUI.class, widgetset = "ru.mycompany.vaadin.demo.AppWidgetSet")
public static class Servlet extends VaadinServlet {
}
#Override
protected void init(VaadinRequest request) {
final VerticalLayout layout = new VerticalLayout();
layout.setMargin(true);
setContent(layout);
addUserNameTextField(layout);
addPasswordTextField(layout);
addButton(layout, request);
}
private void addPasswordTextField(Layout aLayout) {
passwordTextField = new PasswordField("Пароль:");
aLayout.addComponent(passwordTextField);
}
private void addUserNameTextField(final Layout aLayout) {
userNameTextField = new TextField("Пользователь:");
aLayout.addComponent(userNameTextField);
}
private void addButton(final Layout aParent, final VaadinRequest request) {
final Button button = new Button("Войти");
button.addClickListener(new Button.ClickListener() {
public void buttonClick(Button.ClickEvent event) {
final boolean credentialsCorrect = checkCredentials();
if (credentialsCorrect) {
goToMainWindow(request);
} else {
[...]
}
}
});
aParent.addComponent(button);
}
private void goToMainWindow(final VaadinRequest aRequest) {
final MainUI mainUI = new MainUI();
mainUI.init(aRequest);
setContent(mainUI);
}
}
#Theme("mytheme")
#SuppressWarnings("serial")
public class MainUI extends UI {
#Override
protected void init(final VaadinRequest vaadinRequest) {
final HorizontalSplitPanel splitPanel = new HorizontalSplitPanel();
setContent(splitPanel);
splitPanel.setSizeFull();
splitPanel.setSplitPosition(200, Unit.PIXELS);
final String[] tabLabels = new String[] {
"Tree item 1",
"Tree item 2"};
final Tree tree = new Tree();
for (int i=0; i < tabLabels.length; i++)
{
addTreeItem(tree, tabLabels[i]);
}
splitPanel.setFirstComponent(tree);
splitPanel.setSecondComponent(new Label("Test"));
}
private void addTreeItem(final Tree aTree, final String aLabel) {
aTree.addItem(aLabel);
}
}
On the Vaadin forum someone suggested to use the navigator, which solved my problem.
I'd rather think that MainUI should extend HorizontalSplitPanel, not UI. It is strange concept to me to insert one UI into another.
You can use #SpringUI for the main class which extends UI:
#SpringUI
#Theme("mytheme")
#Widgetset("com.MyAppWidgetset")
#PreserveOnRefresh
public class MainUI extends UI {
private static final long serialVersionUID = -8247521108438815011L;
private static Locale locale = VaadinSession.getCurrent().getLocale();
#Autowired
private ToolBoxMessageSource messageSource;
#Autowired
private SpringViewProvider springViewProvider;
public MainUI() {
}
//Initializes navigator with SpringViewProvider and add all existing
//and ui specific assigned views to navigator.
#Override
protected void init(VaadinRequest vaadinRequest) {
Navigator navigator = new Navigator(this, this);
// Adding springViewProvider for spring autowiring
navigator.addProvider(springViewProvider);
// Adding all views for navigation
navigator.addView(LoginView.NAME, LoginView.class);
navigator.addView(MainView.NAME, MainView.class);
navigator.addView(MailToolView.NAME, MailToolView.class);
navigator.addView(AdminView.NAME, AdminView.class);
navigator.addView(EditRecipientView.NAME, EditRecipientView.class);
navigator.addView(EditRecipientsView.NAME, EditRecipientsView.class);
navigator.addView(ServerView.NAME, ServerView.class);
navigator.addView(TestJobView.NAME, TestJobView.class);
navigator.addView("", new LoginView());
navigator.navigateTo(LoginView.NAME);
navigator.setErrorView(LoginView.class);
// security: if user changes view check if the user has the required rights
navigator.addViewChangeListener(new ViewChangeListener() {
private static final long serialVersionUID = 7330051193056583546L;
#Override
public boolean beforeViewChange(ViewChangeEvent event) {
Toolbox toolbox = getSession().getAttribute(Toolbox.class);
if (TbRightManagement.checkAccess(event.getNewView().getClass(), toolbox)) {
return true;
} else {
if (toolbox != null) {
TBNotification.show(messageSource.getMessage("access.denied.title", locale),
messageSource.getMessage("access.denied.no_permissions.msg", locale),
Type.ERROR_MESSAGE);
navigator.navigateTo(MainView.NAME);
return false;
} else {
TBNotification.show(messageSource.getMessage("access.denied.title", locale),
messageSource.getMessage("access.denied.not_loggedin.msg", locale),
Type.ERROR_MESSAGE);
navigator.navigateTo(LoginView.NAME);
return false;
}
}
}
#Override
public void afterViewChange(ViewChangeEvent event) {}
});
}
}
And for the other views, as an example EditRecipientsView should be a #SpringView which extends a Vaadin Designer and implements a Vaadin View.
#SpringView(name = EditRecipientsView.NAME)
#Theme("mytheme")
#TbRight(loggedIn = true, mailTool = true)
public class EditRecipientsView extends RecipientsDesign implements View {
private static final long serialVersionUID = 1L;
public static final String NAME = "editRecipients";
private static Locale locale = VaadinSession.getCurrent().getLocale();
private BeanItemContainer<Recipient> recipientContainer;
private Uploader uploader;
#Autowired
private ToolBoxMessageSource messageSource;
public EditRecipientsView() {
super();
}
//Initializes the ui components of the recipient view.
#PostConstruct
public void init() {
btn_addRecipient.addClickListener(e -> { MainUI.getCurrent().getNavigator().navigateTo(EditRecipientView.NAME);});
}
//Handling data when entering this view.
#Override
public void enter(ViewChangeEvent event) {
if (getSession().getAttribute(UIMailing.class) != null) {
List<Recipient> recipientList = getSession().getAttribute(UIMailing.class).getRecipients();
if (recipientList != null) {
recipientContainer.removeAllItems();
} else {
recipientList = new ArrayList<Recipient>();
}
recipientContainer.addAll(recipientList);
recipient_table.sort(new Object[] {"foreName", "lastName"}, new boolean[] {true, true});
}
}
}

Resources