After upgrading from Wicket 6.23.0 to 7.4.0 the Login on my Wicket Page does not work anymore.
I get an PageExpiredException:
14:50:31,772 WARN [RequestCycleExtra] (default task-20) ********************************
14:50:31,773 WARN [RequestCycleExtra] (default task-20) Handling the following exception: org.apache.wicket.protocol.http.PageExpiredException: Bookmarkable page with id 'null' has expired.
14:50:31,774 WARN [RequestCycleExtra] (default task-20) ********************************
The LoginPage looks like this:
#MountPath("login")
public class LoginPage extends WebPage {
private static final long serialVersionUID = 1L;
public LoginPage() {
}
#Override
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
response.render(JavaScriptReferenceHeaderItem.forReference(JQueryJavaScriptResourceReference.get()));
response.render(JavaScriptReferenceHeaderItem.forReference(JQueryUiJavaScriptResourceReference.get()));
response.render(CssContentHeaderItem.forReference(JQueryUiCssResourceReference.get()));
}
#Override
protected void onInitialize() {
super.onInitialize();
IModel<AuthenticationData> model = new CompoundPropertyModel<>(new AuthenticationData());
add(new FeedbackPanel("feedbackPanel"));
#SuppressWarnings("serial")
StatelessForm<AuthenticationData> form = new StatelessForm<AuthenticationData>("form", model) {
/** {#inheritDoc} */
#Override
protected void onSubmit() {
WebSession session = WebSession.get();
if (session.signIn(getModelObject().getUserName(), getModelObject().getPassword())) {
setResponsePage(getApplication().getHomePage());
} else {
error("Login failed due to invalid credentials");
}
}
};
add(form);
TextField<String> userNameTextField = new TextField<>("userName");
form.add(userNameTextField);
PasswordTextField passwordTextField = new PasswordTextField("password");
form.add(passwordTextField);
SubmitLink submitLink = new SubmitLink("submitLink");
form.add(submitLink);
form.setDefaultButton(submitLink);
}
}
The onSubmit Method of the StatelessForm is never reached.
The setup is simular to here: https://ci.apache.org/projects/wicket/guide/7.x/guide/security.html#security_1
The problem was the StatelessForm on the LoginPage:
#MountPath("login")
public class LoginPage extends WebPage {
private static final long serialVersionUID = 1L;
public LoginPage() {
}
#Override
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
response.render(JavaScriptReferenceHeaderItem.forReference(JQueryJavaScriptResourceReference.get()));
response.render(JavaScriptReferenceHeaderItem.forReference(JQueryUiJavaScriptResourceReference.get()));
response.render(CssContentHeaderItem.forReference(JQueryUiCssResourceReference.get()));
}
#Override
protected void onInitialize() {
super.onInitialize();
IModel<AuthenticationData> model = new CompoundPropertyModel<>(new AuthenticationData());
add(new FeedbackPanel("feedbackPanel"));
#SuppressWarnings("serial")
Form<AuthenticationData> form = new Form<AuthenticationData>("form", model) {
/** {#inheritDoc} */
#Override
protected void onSubmit() {
WebSession session = WebSession.get();
if (session.signIn(getModelObject().getUserName(), getModelObject().getPassword())) {
setResponsePage(getApplication().getHomePage());
} else {
error("Login failed due to invalid credentials");
}
}
};
add(form);
TextField<String> userNameTextField = new TextField<>("userName");
form.add(userNameTextField);
PasswordTextField passwordTextField = new PasswordTextField("password");
form.add(passwordTextField);
SubmitLink submitLink = new SubmitLink("submitLink");
form.add(submitLink);
form.setDefaultButton(submitLink);
}
}
Related
I use spring, hibernate, jpa2.1.
as follow:
#Entity
#EntityListeners(DemoListener.class)
public class Demo {
#Id
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
public class DemoListener {
#PersistenceContext
private EntityManager entityManager;
#PrePersist
public void prePersist(Demo demo){
}
}
the example works well, when I want to add more listener, I must modify the Demo entity, but the Demo is in other jar,I don't want to use the XML configuration, is there some way like this:
...addListener(Demo.class, new DemoListener());
...addListener(Demo.class, new OtherDemoListener());
base on hibernate-orm docs and hibernate-tutorials:
/**
* #param <T> one of {#link EventType#baseListenerInterface()}
* #see org.hibernate.event.service.spi.EventListenerRegistry
*/
public interface JpaEventListenerRegistry<T> {
/**
* add listener for entity class
*
* #param entityClass can't be null
* #param listener can't be null
*/
void addListener(Class<?> entityClass, T listener);
}
public class JpaEventListenerRegistryImpl implements JpaEventListenerRegistry<Object> {
private Logger logger = LoggerFactory.getLogger(getClass());
private EventListenerRegistry eventListenerRegistry;
private Map<EventType, JpaEventListenerRegistry> listeners = new HashMap<EventType, JpaEventListenerRegistry>();
public JpaEventListenerRegistryImpl(EventListenerRegistry eventListenerRegistry) {
this.eventListenerRegistry = eventListenerRegistry;
initDefault();
}
private void initDefault() {
listeners.put(EventType.PRE_INSERT, new DomainPreInsertEventListener());
listeners.put(EventType.POST_INSERT, new DomainPostInsertEventListener());
for (Map.Entry<EventType, JpaEventListenerRegistry> entry : listeners.entrySet()) {
eventListenerRegistry.appendListeners(entry.getKey(), entry.getValue());
}
}
#SuppressWarnings("unchecked")
public void addListener(Class<?> entityClass, Object listener) {
logger.info("add listener {} for entity {}", listener, entityClass.getName());
for (EventType eventType : EventType.values()) {
Class<?> listenerInterface = eventType.baseListenerInterface();
if (listenerInterface.isAssignableFrom(listener.getClass())) {
JpaEventListenerRegistry registry = listeners.get(eventType);
if (registry == null) {
logger.warn("the event type {} for listener {} is not supported", eventType, listener);
} else {
registry.addListener(entityClass, listener);
}
}
}
}
public static class Abstract<T> implements JpaEventListenerRegistry<T> {
private Logger logger = LoggerFactory.getLogger(getClass());
private Map<Class<?>, List<T>> listeners = new HashMap<Class<?>, List<T>>();
public void addListener(Class<?> entityClass, T listener) {
logger.info("add listener {} for entity {}", listener, entityClass.getName());
List<T> listeners = this.listeners.get(entityClass);
if (listeners == null) {
listeners = new ArrayList<T>();
this.listeners.put(entityClass, listeners);
}
listeners.add(listener);
}
List<T> findListener(Class<?> entityClass) {
for (Map.Entry<Class<?>, List<T>> entry : listeners.entrySet()) {
if (entry.getKey().isAssignableFrom(entityClass)) {
return entry.getValue();
}
}
return null;
}
}
public static class DomainPreInsertEventListener extends Abstract<PreInsertEventListener> implements PreInsertEventListener {
public boolean onPreInsert(PreInsertEvent event) {
return onPreInsert(event, findListener(event.getEntity().getClass()));
}
private boolean onPreInsert(PreInsertEvent event, List<PreInsertEventListener> listeners) {
if (listeners == null) return false;
for (PreInsertEventListener listener : listeners) {
if (listener.onPreInsert(event)) return true;
}
return false;
}
}
public static class DomainPostInsertEventListener extends Abstract<PostInsertEventListener> implements PostInsertEventListener {
public void onPostInsert(PostInsertEvent event) {
onPostInsert(event, findListener(event.getEntity().getClass()));
}
private void onPostInsert(PostInsertEvent event, List<PostInsertEventListener> listeners) {
if (listeners == null) return;
for (PostInsertEventListener listener : listeners) {
listener.onPostInsert(event);
}
}
public boolean requiresPostCommitHanding(EntityPersister persister) {
return false;
}
}
}
public class EntityManagerIllustrationTest extends TestCase {
private EntityManagerFactory entityManagerFactory;
#Override
protected void setUp() throws Exception {
// like discussed with regards to SessionFactory, an EntityManagerFactory is set up once for an application
// IMPORTANT: notice how the name here matches the name we gave the persistence-unit in persistence.xml!
entityManagerFactory = Persistence.createEntityManagerFactory("org.hibernate.tutorial.jpa");
SessionFactoryImplementor sessionFactory = entityManagerFactory.unwrap(SessionFactoryImplementor.class);
EventListenerRegistry eventListenerRegistry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class);
JpaEventListenerRegistryImpl jpaEventListenerRegistry = new JpaEventListenerRegistryImpl(eventListenerRegistry);
jpaEventListenerRegistry.addListener(EventListener.class, new JpaEventListener());
}
private static class JpaEventListener implements PreInsertEventListener, PostInsertEventListener {
public boolean onPreInsert(PreInsertEvent event) {
Event entity = (Event) event.getEntity();
System.out.println("onPreInsert:" + entity);
return false;
}
public void onPostInsert(PostInsertEvent event) {
Event entity = (Event) event.getEntity();
System.out.println("onPostInsert:" + entity);
}
public boolean requiresPostCommitHanding(EntityPersister persister) {
return false;
}
}
#Override
protected void tearDown() throws Exception {
entityManagerFactory.close();
}
public void testBasicUsage() {
// create a couple of events...
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
entityManager.persist(new Event("Our very first event!", new Date()));
// entityManager.persist(new Event("A follow up event", new Date()));
entityManager.getTransaction().commit();
entityManager.close();
// now lets pull events from the database and list them
entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
List<Event> result = entityManager.createQuery("from Event", Event.class).getResultList();
for (Event event : result) {
System.out.println("Event (" + event.getDate() + ") : " + event.getTitle());
}
entityManager.getTransaction().commit();
entityManager.close();
}
}
How can I add terminate button to eclipse console toolbar? I create console in this way:
IOConsole console = new IOConsole( name, null, null, true );
ConsolePlugin.getDefault().getConsoleManager().addConsoles( new IConsole[]{console} );
I found solution. Here is the code:
<extension
point="org.eclipse.ui.console.consolePageParticipants">
<consolePageParticipant
class="com.plugin.console.ConsoleActions"
id="com.plugin.console.PageParticipant">
<enablement>
<instanceof value="com.plugin.console.Console"/>
</enablement>
</consolePageParticipant>
</extension>
Console class:
public class Console extends IOConsole {
public Console(String name, ImageDescriptor imageDescriptor) {
super(name, imageDescriptor);
}
public Console(String name, String consoleType, ImageDescriptor imageDescriptor, boolean autoLifeCycle) {
super(name, consoleType, imageDescriptor, autoLifeCycle);
}
}
Console Participant class:
public class ConsoleActions implements IConsolePageParticipant {
private IPageBookViewPage page;
private Action remove, stop;
private IActionBars bars;
private IConsole console;
#Override
public void init(final IPageBookViewPage page, final IConsole console) {
this.console = console;
this.page = page;
IPageSite site = page.getSite();
this.bars = site.getActionBars();
createTerminateAllButton();
createRemoveButton();
bars.getMenuManager().add(new Separator());
bars.getMenuManager().add(remove);
IToolBarManager toolbarManager = bars.getToolBarManager();
toolbarManager.appendToGroup(IConsoleConstants.LAUNCH_GROUP, stop);
toolbarManager.appendToGroup(IConsoleConstants.LAUNCH_GROUP,remove);
bars.updateActionBars();
}
private void createTerminateAllButton() {
ImageDescriptor imageDescriptor = ImageDescriptor.createFromFile(getClass(), "/icons/stop_all_active.gif");
this.stop = new Action("Terminate all", imageDescriptor) {
public void run() {
//code to execute when button is pressed
}
};
}
private void createRemoveButton() {
ImageDescriptor imageDescriptor = ImageDescriptor.createFromFile(getClass(), "/icons/remove_active.gif");
this.remove= new Action("Remove console", imageDescriptor) {
public void run() {
//code to execute when button is pressed
}
};
}
#Override
public void dispose() {
remove= null;
stop = null;
bars = null;
page = null;
}
#Override
public Object getAdapter(Class adapter) {
return null;
}
#Override
public void activated() {
updateVis();
}
#Override
public void deactivated() {
updateVis();
}
private void updateVis() {
if (page == null)
return;
boolean isEnabled = true;
stop.setEnabled(isEnabled);
remove.setEnabled(isEnabled);
bars.updateActionBars();
}
}
I'm building a wicket bootsrap web application with the following specs (from pom.xml):
wicket version: 6.15.0
wicket-bootstrap-core.version: 0.9.3-SNAPSHOT
I have a base page which is the father of my other pages and adds to mark up a horizontal navigation bar on top, with key component:
BootstrapBookmarkablePageLink extends BookmarkablePageLink
This is part of my BasePage.java
public abstract class BasePage extends GenericWebPage<Void> {
private static final long serialVersionUID = 1L;
String username;
public WicketApplication getApp() {
return WicketApplication.class.cast(getApplication());
}
public BasePage(final PageParameters parameters) {
super(parameters);
// Read session data
cachedUsername = (String)
BasicAuthenticationSession.get().getAttribute("username");
// create navbar
add(newNavbar("navbar"));
}
/**
* #return application properties
*/
public Properties getProperties() {
return WicketApplication.get().getProperties();
}
/**
* creates a new {#link Navbar} instance
*
* #param markupId
* The components markup id.
* #return a new {#link Navbar} instance
*/
protected Navbar newNavbar(String markupId) {
Navbar navbar = new Navbar(markupId) {
private static final long serialVersionUID = 1L;
#Override
protected TransparentWebMarkupContainer newCollapseContainer(String
componentId) {
TransparentWebMarkupContainer container =
super.newCollapseContainer(componentId);
container.add(new CssClassNameAppender("bs-navbar-collapse"));
return container;
}
};
navbar.setPosition(Navbar.Position.TOP);
// navbar.setInverted(true);
NavbarButton<Void> myTab = new NavbarButton<Void>(MyPage.class, new
PageParameters().add("name", "")
.add("status", "All").add("date", ""), Model.of("My page"));
NavbarButton<Void> myOtherTab = new NavbarButton<Void>
(MyOtherPage.class, new PageParameters().add("status", "initial")
.add("date", ""), Model.of("My other page"));
navbar.addComponents(NavbarComponents.transform(
Navbar.ComponentPosition.LEFT,
myTab, myOtherTab));
return navbar;
}
}
Then, MyPage renders a filter form, an html table, ajaxbuttons and some links, Some of my components are ajax components:
public class MyPage extends BasePage {
private static final long serialVersionUID = 5772520351966806522L;
#SuppressWarnings("unused")
private static final Logger LOG = LoggerFactory.getLogger(MyPage.class);
private static final Integer DAYS = 270;
private DashboardFilteringPageForm filteringForm;
private CityInitialForm ncForm;
private String CityName;
private String startDate;
private CitysTablePanel citysTable;
private WebMarkupContainer numberOfNodes;
public MyPage(PageParameters parameters) throws ParseException {
super(parameters);
// get Citys list from repo
final List<City> repoCitys = (List<City>) methodToGetCities();
// select number of nodes
numberOfNodes = new WebMarkupContainer("numberOfNodes") {
private static final long serialVersionUID = 5772520351966806522L;
};
numberOfNodes.setOutputMarkupId(true);
ncForm = new CityInitialForm("ncForm");
// validation
add(new FeedbackPanel("feedbackPanel")).setOutputMarkupId(true);
ncForm.getNumberField().setRequired(true);
ncForm.add(new AjaxButton("ncButton") {
private static final long serialVersionUID = -6846211690328190809L;
#Override
protected void onInitialize() {
super.onInitialize();
add(newAjaxFormSubmitBehavior("change"));
}
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
// redirect to other page
}
#Override
protected void updateAjaxAttributes(AjaxRequestAttributes
attributes) {
super.updateAjaxAttributes(attributes);
attributes.getAjaxCallListeners().add(new
DisableComponentListener(citysTable));
}
});
numberOfNodes.add(ncForm);
// filters
CityName = parameters.get("name").toString() == null ? "" :
parameters.get("name").toString();
startDate = parameters.get("date").toString();
filteringForm = new DashboardFilteringPageForm("filteringForm") {
private static final long serialVersionUID = -1702151172272765464L;
};
// initialize form inputs
filteringForm.setCityName(CityName);
try {
filteringForm.setStartDate(new SimpleDateFormat("EE MMM dd HH:mm:ss
z yyyy", Locale.ENGLISH)
.parse(getStartDate().equals("") ?
CortexWebUtil.subtractDays(new Date(), DAYS).toString() : getStartDate()));
} catch (Exception e) {
setResponsePage(SignInPage.class, new PageParameters());
}
filteringForm.add(new AjaxButton("button") {
private static final long serialVersionUID = -6846211690328190809L;
#Override
protected void onInitialize() {
super.onInitialize();
add(newAjaxFormSubmitBehavior("change"));
}
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> paForm) {
// retrieve Citys
filterCitysAjax(target, "All");
}
#Override
protected void updateAjaxAttributes(AjaxRequestAttributes
attributes) {
super.updateAjaxAttributes(attributes);
attributes.getAjaxCallListeners().add(new
DisableComponentListener(citysTable));
}
});
filteringForm.getCityNameTextField().add(new OnChangeAjaxBehavior() {
private static final long serialVersionUID = 1468056167693038096L;
#Override
protected void onUpdate(AjaxRequestTarget target) {
try {
filterCitysAjax(target, "All");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
#Override
protected void updateAjaxAttributes(AjaxRequestAttributes
attributes) {
super.updateAjaxAttributes(attributes);
attributes.getAjaxCallListeners().add(new
DisableComponentListener(citysTable));
}
});
// new City link
AjaxLink<Void> newCityLink = newCityLink("newCity", repoCitys);
// Citys table
citysTable = new CitysTablePanel("CitysTable", repoCitys);
citysTable.setOutputMarkupId(true);
// add components
add(filteringForm, newCityLink, numberOfNodes, citysTable);
}
private void filterCitysAjax(AjaxRequestTarget target, String status) {
methodToFilterResults();
// re-render table component
CitysTablePanel cityTableNew = new CitysTablePanel("CitysTable", citys);
cityTableNew.setOutputMarkupId(true);
cityTableNew.setVisibilityAllowed(true);
cityTableNew.setVisible(true);
citysTable.replaceWith(cityTableNew);
target.add(cityTableNew);
citysTable = cityTableNew;
target.appendJavaScript(CortexWebUtil.TABLE_ODD_EVEN_ROWS);
}
private AjaxLink<Void> newCityLink(String string, final List<City> Citys) {
final AjaxLink<Void> newCityLink = new AjaxLink<Void>(string) {
private static final long serialVersionUID = -5420108740617806989L;
#Override
public void onClick(final AjaxRequestTarget target) {
numberOfNodes.add(new AttributeModifier("style",
"display:block"));
target.add(numberOfNodes);
}
};
// new City image
Image newCityImage = new Image("newCityIcon", new
ContextRelativeResource("/img/new_City_icon.png"));
add(newCityLink);
newCityLink.add(newCityImage);
return newCityLink;
}
}
So MyPage works but when I open MyOtherPage Link in an a new tab and trigger an ajax component in MyPage (e.g the AjaxButton) then I get the page expirtaion error.
Why is that happening?
Do I need to use stateless pages? ( stateless link )
Why would it be so ard in wicket to open links in new tabs and use ajax components? I must be missing sometthing..
Here are few possible reasons:
MyPage fails to serialize
Wicket stores stateful pages in page storage (in the disk, by default). Later when you click a stateful link Wicket tries to load the page. First it looks in the http session where the page is kept in its live form (i.e. not serialized). If it is not found there then Wicket looks in the disk.
Wicket keeps only the page(s) used in the last user request in the Http Session (to keep memory footprint small). By clicking on MyOtherPage link you put an instance of MyOtherPage in the Http session and the old instance (of MyPage) is only in the disk. But: if MyPage fails to serialize to byte[] then it cannot be stored in the disk and thus later requests will fail with PageExpiredException.
Todo: Check your logs for NotSerializableException with nice debug message of the reason.
MyOtherPage is too big
By default Wicket writes up to 10M per user session in the disk. If MyPage is let's say 2M and MyOtherPage is 9M (both sizes are quite big, but I don't know what happens in your app...) then saving MyOtherPage will remove MyPage from the disk. Later attempts to load MyPage will fail with PageExpiredException.
Todo: Review your usage of Wicket Models.
For a project,i want to switch the project from simple broker to full-feature broker(like rabiitmq, apollo).
the exception stack:
Caused by: org.springframework.messaging.MessageDeliveryException: Message broker is not active.
at org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler.handleMessageInternal(StompBrokerRelayMessageHandler.java:392)
at org.springframework.messaging.simp.broker.AbstractBrokerMessageHandler.handleMessage(AbstractBrokerMessageHandler.java:177)
at org.springframework.messaging.support.ExecutorSubscribableChannel.sendInternal(ExecutorSubscribableChannel.java:64)
at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:116)
at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:98)
at org.springframework.messaging.simp.SimpMessagingTemplate.doSend(SimpMessagingTemplate.java:125)
at org.springframework.messaging.simp.SimpMessagingTemplate.doSend(SimpMessagingTemplate.java:48)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:94)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.convertAndSend(AbstractMessageSendingTemplate.java:144)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.convertAndSend(AbstractMessageSendingTemplate.java:112)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.convertAndSend(AbstractMessageSendingTemplate.java:107)
at cn.clickmed.cmcp.websocket.plain.util.WebSocketUtil.sendMessage(WebSocketUtil.java:61)
at cn.clickmed.cmcp.websocket.plain.util.WebSocketUtil.sendMessage(WebSocketUtil.java:65)
at cn.clickmed.cmcp.websocket.plain.entity.WebSocketEntity.postPersist(WebSocketEntity.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
here is the config code:
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer{
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
for(String mapping : WebSocketConstant.WEBSOCKETTYPE.keySet()) {
registry.addEndpoint(mapping).withSockJS();
}
}
#Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/websocket");
// registry.enableSimpleBroker("/topic");
registry.enableStompBrokerRelay("/topic","/queue").setRelayHost("localhost").setRelayPort(61613).setSystemHeartbeatReceiveInterval(2000).setSystemHeartbeatSendInterval(2000);
// registry.setUserDestinationPrefix("/topic/");
}
#Bean
public Broker broker() throws Exception {
final Broker broker = new Broker();
// Configure STOMP over WebSockects connector
final AcceptingConnectorDTO ws = new AcceptingConnectorDTO();
ws.id = "ws";
ws.bind = "ws://localhost:61613";
ws.protocols.add( new StompDTO() );
// Create a topic with name 'test'
final TopicDTO topic = new TopicDTO();
topic.id = "todoListener";
// Create virtual host (based on localhost)
final VirtualHostDTO host = new VirtualHostDTO();
host.id = "localhost";
host.topics.add( topic );
host.host_names.add( "localhost" );
host.host_names.add( "127.0.0.1" );
host.auto_create_destinations = false;
// Create a web admin UI (REST) accessible at: http://localhost:61680/api/index.html#!/
final WebAdminDTO webadmin = new WebAdminDTO();
webadmin.bind = "http://localhost:61680";
// Create JMX instrumentation
final JmxDTO jmxService = new JmxDTO();
jmxService.enabled = true;
// Finally, glue all together inside broker configuration
final BrokerDTO config = new BrokerDTO();
config.connectors.add( ws );
config.virtual_hosts.add( host );
config.web_admins.add( webadmin );
config.services.add( jmxService );
broker.setConfig( config );
broker.setTmp( new File( System.getProperty( "java.io.tmpdir" ) ) );
broker.start( new Runnable() {
#Override
public void run() {
System.out.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:启动了");
}
} );
return broker;
}
}
send message code:
public class WebSocketUtil implements ILog{
public static Map<String, List<WebSocketSession>> webSocketSessionMap = new HashMap<String, List<WebSocketSession>>();
public static SimpMessagingTemplate simpMessagingTemplate = null;
public static void doSendMessage(String webSocketType) throws IOException {
if(WebSocketUtil.webSocketSessionMap.get(webSocketType) != null) {
String msg = "";
if(WebSocketConstant.WEBSOCKETTYPE_TODOLIST.equals(webSocketType)) {
msg = "change";
}
for(WebSocketSession webSocketSession :WebSocketUtil.webSocketSessionMap.get(webSocketType)) {
webSocketSession.sendMessage(new TextMessage(msg));
}
}
}
public static String getWebSocketType(String url) {
int length = url.indexOf("/cmcp/");
String theUrl = url.substring(length+5);
if(theUrl.startsWith(WebSocketConstant.COMPATIBLEMAPPING)) {
String [] arr = theUrl.split("/");
theUrl = "/"+arr[2];
}
if(!WebSocketConstant.WEBSOCKETTYPE.containsKey(theUrl)) {
logger.error("please config the websocketConstant !!!!");
throw new RuntimeException();
}
String theType = WebSocketConstant.WEBSOCKETTYPE.get(theUrl);
return theType;
}
public synchronized static void initSimpMessagingTemplate() {
if(simpMessagingTemplate == null) {
simpMessagingTemplate = SpringUtil.getBeanByName("brokerMessagingTemplate");
}
}
public static void sendMessage(String topic, String message) {
if(simpMessagingTemplate == null) {
initSimpMessagingTemplate();
}
simpMessagingTemplate.convertAndSend("/topic"+topic, message);
}
public static void sendMessage(String topic) {
sendMessage(topic,"change");
}
}
this is the trigger entity:
#MappedSuperclass
public class WebSocketEntity extends CommonEntity {
/**
* serialVersionUID
*/
private static final long serialVersionUID = 1L;
#PostPersist
public void postPersist() throws IOException{
if(this instanceof TodoEntity) {
WebSocketUtil.sendMessage(WebSocketConstant.WEBSOCKETTYPE_TODOLIST_MAPPING);
}
}
#PostRemove
public void postRemove() throws IOException{
if(this instanceof TodoEntity) {
WebSocketUtil.sendMessage(WebSocketConstant.WEBSOCKETTYPE_TODOLIST_MAPPING);
}
}
}
please give me help! thanks!
Hi I'm trying to retrieve a linkedhashset from the Google datastore but nothing seems to happen. I want to display the results in a Grid using GWT on a page. I have put system.out.println() in all the classes to see where I go wrong but it only shows one and I don't recieve any errors. I use 6 classes 2 in the server package(ContactDAOJdo/ContactServiceImpl) and 4 in the client package(ContactService/ContactServiceAsync/ContactListDelegate/ContactListGui). I hope someone can explain why this isn't worken and point me in the right direction.
public class ContactDAOJdo implements ContactDAO {
#SuppressWarnings("unchecked")
#Override
public LinkedHashSet<Contact> listContacts() {
PersistenceManager pm = PmfSingleton.get().getPersistenceManager();
String query = "select from " + Contact.class.getName();
System.out.print("ContactDAOJdo: ");
return (LinkedHashSet<Contact>) pm.newQuery(query).execute();
}
}
public class ContactServiceImpl extends RemoteServiceServlet implements ContactService{
private static final long serialVersionUID = 1L;
private ContactDAO contactDAO = new ContactDAOJdo() {
#Override
public LinkedHashSet<Contact> listContacts() {
LinkedHashSet<Contact> contacts = contactDAO.listContacts();
System.out.println("service imp "+contacts);
return contacts;
}
}
#RemoteServiceRelativePath("contact")
public interface ContactService extends RemoteService {
LinkedHashSet<Contact> listContacts();
}
public interface ContactServiceAsync {
void listContacts(AsyncCallback<LinkedHashSet <Contact>> callback);
}
public class ListContactDelegate {
private ContactServiceAsync contactService = GWT.create(ContactService.class);
ListContactGUI gui;
void listContacts(){
contactService.listContacts(new AsyncCallback<LinkedHashSet<Contact>> () {
public void onFailure(Throwable caught) {
gui.service_eventListContactenFailed(caught);
System.out.println("delegate "+caught);
}
public void onSuccess(LinkedHashSet<Contact> result) {
gui.service_eventListRetrievedFromService(result);
System.out.println("delegate "+result);
}
});
}
}
public class ListContactGUI {
protected Grid contactlijst;
protected ListContactDelegate listContactService;
private Label status;
public void init() {
status = new Label();
contactlijst = new Grid();
contactlijst.setVisible(false);
status.setText("Contact list is being retrieved");
placeWidgets();
}
public void service_eventListRetrievedFromService(LinkedHashSet<Contact> result){
System.out.println("1 service eventListRetreivedFromService "+result);
status.setText("Retrieved contactlist list");
contactlijst.setVisible(true);
this.contactlijst.clear();
this.contactlijst.resizeRows(1 + result.size());
int row = 1;
this.contactlijst.setWidget(0, 0, new Label ("Voornaam"));
this.contactlijst.setWidget(0, 1, new Label ("Achternaam"));
for(Contact contact: result) {
this.contactlijst.setWidget(row, 0, new Label (contact.getVoornaam()));
this.contactlijst.setWidget(row, 1, new Label (contact.getVoornaam()));
row++;
System.out.println("voornaam: "+contact.getVoornaam());
}
System.out.println("2 service eventListRetreivedFromService "+result);
}
public void placeWidgets() {
System.out.println("placewidget inside listcontactgui" + contactlijst);
RootPanel.get("status").add(status);
RootPanel.get("contactlijst").add(contactlijst);
}
public void service_eventListContactenFailed(Throwable caught) {
status.setText("Unable to retrieve contact list from database.");
}
}
It could be the query returns a lazy list. Which means not all values are in the list at the moment the list is send to the client. I used a trick to just call size() on the list (not sure how I got to that solution, but seems to work):
public LinkedHashSet<Contact> listContacts() {
final PersistenceManager pm = PmfSingleton.get().getPersistenceManager();
try {
final LinkedHashSet<Contact> contacts =
(LinkedHashSet<Contact>) pm.newQuery(Contact.class).execute();
contacts.size(); // this triggers to get all values.
return contacts;
} finally {
pm.close();
}
}
But I'm not sure if this is the best practice...